Changeset 251226 in webkit


Ignore:
Timestamp:
Oct 16, 2019 10:45:58 PM (5 years ago)
Author:
mark.lam@apple.com
Message:

Reduce the amount of memory needed to store Options.
https://bugs.webkit.org/show_bug.cgi?id=202105

Reviewed by Yusuke Suzuki.

The size of the JSC::Config needed to store the Options is now reduced to 4K
instead of 16K, enabled by constexpr template magic.

  1. Instead of all options in a large array of OptionEntry (which is a union of all the option types), we now have separate arrays for each of the types of options. For example,

Removed g_jscConfig.options[].
Added g_jscConfig.typeBoolOptions[].
Added g_jscConfig.typeInt32Options[].
Added g_jscConfig.typeDoubleOptions[].
...

We used to find the storage for the option using g_jscConfig.options[Options::ID].
We now find the storage for each type of option using
g_jscConfig.options[optionTypeSpecificIndex<OptionTypeID, OptionID>()]. For
example, Options::useJIT() used to be implemented as:

inline bool& Options::useJIT()
{

return g_jscConfig.options[Options::useJITID];

}

... which is now replaced with:

inline bool& Options::useJIT()
{

return g_jscConfig.typeBoolOptions[optionTypeSpecificIndex<OptionTypeID::Bool, OptionID::useJIT>()];

}

MSVC has a bug where it cannot handle very large source files: see
https://developercommunity.visualstudio.com/content/problem/653301/fatal-error-c1002-compiler-is-out-of-heap-space-in.html.
This bug prevents this patch from building on MSVC. To workaround this bug,
we don't inline the Options accessors when COMPILER(MSVC). This prevents MSVC
from having to parse the large body of template code code to used to implement
the inline accessors in every file that #include "Options.h".

Also add the @no-unify attribute to Options.cpp (where we put the accessors)
so that it doesn't trigger the MSVC bug also.

  1. Introduce the optionTypeSpecificIndex() constexpr template function for computing the index of each option in their respective type specific options array.
  1. Introduce OptionTypes, OptionTypeID, and OptionID.

The OptionTypes namespace replaces OptionEntry as the container of option types.
The OptionID enum class replaces Options::ID.
The OptionTypeID enum class is new and is used together with OptionID in

constexpr templates to compute the typeSpecificIndex of options.

  1. Removed the OptionEntry struct and OptionEntry.h. After (1), this struct is only used in the Option class. We just moved the union of option types (that OptionEntry embeds) into the Option class.

Moved class OptionRange into OptionsList.h.

  1. Removed the large OptionEntry arrays from JSC::Config. Added type specific options arrays. Also ordered these arrays to maximize compactness and minimize internal fragmentation.
  1. Changed scaleJITPolicy() to go directly to g_jscConfig.typeInt32Options[] instead of going through the Option wrapper object. This allows us to simplify things and make the Option class a read only interface of options.
  1. Changed Options::initialize() to only compute the option default value once. The default value specified in the OptionsList may not always be a constant. Sometimes, it is a function call.
  1. The Option class now only gives read only access to the options.

The Option class' role is to provide an interface for reading an option at any
given OptionID without first knowing about the type of the specific option.
It is useful for iterating options, and is currently only used by
Options::dumpOption().

Technically, we could merge all the Option class code into its single client.
We opted not to do this because the amount of code is non-trivial, and the
Option class does a good job of encapsulating this functionality.

  • API/glib/JSCOptions.cpp:

(jscOptionsSetValue):
(jscOptionsGetValue):
(jsc_options_foreach):
(jsc_options_get_option_group):

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • runtime/JSCConfig.h:
  • runtime/OptionEntry.h: Removed.
  • runtime/Options.cpp:

(JSC::Options::isAvailable):
(JSC::overrideOptionWithHeuristic):
(JSC::optionTypeSpecificIndex):
(JSC::scaleJITPolicy):
(JSC::recomputeDependentOptions):
(JSC::Options::initialize):
(JSC::Options::setOptionWithoutAlias):
(JSC::Options::dumpAllOptions):
(JSC::Options::dumpOption):
(JSC::Option::Option):
(JSC::Option::defaultOption const):
(JSC::Option::dump const):
(JSC::Option::operator== const):

  • runtime/Options.h:

(JSC::Option::id const):
(JSC::Option::name const):
(JSC::Option::description const):
(JSC::Option::type const):
(JSC::Option::availability const):
(JSC::Option::isOverridden const):
(JSC::Option::Option):
(JSC::Option::idIndex const):
(JSC::optionTypeSpecificIndex):
(JSC::Option::defaultOption const): Deleted.
(JSC::Option::boolVal): Deleted.
(JSC::Option::unsignedVal): Deleted.
(JSC::Option::doubleVal): Deleted.
(JSC::Option::int32Val): Deleted.
(JSC::Option::optionRangeVal): Deleted.
(JSC::Option::optionStringVal): Deleted.
(JSC::Option::gcLogLevelVal): Deleted.

  • runtime/OptionsList.h:

(JSC::OptionRange::operator= ):
(JSC::OptionRange::rangeString const):
(JSC::countNumberOfJSCOptionsOfType):

Location:
trunk/Source/JavaScriptCore
Files:
1 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/glib/JSCOptions.cpp

    r250278 r251226  
    169169#define SET_OPTION_VALUE(type_, name_, defaultValue_, availability_, description_) \
    170170    if (!g_strcmp0(#name_, option)) {                                   \
    171         OptionEntry::type_ valueToSet;                                  \
     171        OptionTypes::type_ valueToSet;                                  \
    172172        if (!valueFromGValue(value, valueToSet))                        \
    173173            return FALSE;                                               \
     
    187187#define GET_OPTION_VALUE(type_, name_, defaultValue_, availability_, description_) \
    188188    if (!g_strcmp0(#name_, option)) {                                   \
    189         OptionEntry::type_ valueToGet = Options::name_();               \
     189        OptionTypes::type_ valueToGet = Options::name_();               \
    190190        valueToGValue(valueToGet, value);                               \
    191191        return TRUE;                                                    \
     
    617617#define VISIT_OPTION(type_, name_, defaultValue_, availability_, description_) \
    618618    if (Options::Availability::availability_ == Options::Availability::Normal \
    619         || Options::isAvailable(Options::name_##ID, Options::Availability::availability_)) { \
    620         OptionEntry::type_ defaultValue { };                            \
     619        || Options::isAvailable(OptionID::name_, Options::Availability::availability_)) { \
     620        OptionTypes::type_ defaultValue { };                            \
    621621        auto optionType = jscOptionsType(defaultValue);                 \
    622622        if (function (#name_, optionType, description_, userData))      \
     
    667667#define REGISTER_OPTION(type_, name_, defaultValue_, availability_, description_) \
    668668    if (Options::Availability::availability_ == Options::Availability::Normal \
    669         || Options::isAvailable(Options::name_##ID, Options::Availability::availability_)) { \
     669        || Options::isAvailable(OptionID::name_, Options::Availability::availability_)) { \
    670670        GUniquePtr<char> name(g_strdup_printf("jsc-%s", #name_));       \
    671671        entries = g_array_set_size(entries, entries->len + 1); \
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r250289 r251226  
    921921    runtime/ObjectPrototype.h
    922922    runtime/Operations.h
    923     runtime/OptionEntry.h
    924923    runtime/Options.h
    925924    runtime/OptionsList.h
  • trunk/Source/JavaScriptCore/ChangeLog

    r251209 r251226  
     12019-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
    11352019-10-16  Keith Miller  <keith_miller@apple.com>
    2136
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r251036 r251226  
    18651865                FE1BD0251E72053800134BC9 /* HeapVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1BD0231E72052F00134BC9 /* HeapVerifier.h */; };
    18661866                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 */; };
    18671868                FE1E2C3F2240DD5800F6B729 /* MacroAssemblerARM64E.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1E2C3E2240D30B00F6B729 /* MacroAssemblerARM64E.h */; settings = {ATTRIBUTES = (Private, ); }; };
    18681869                FE1E2C402240DD6200F6B729 /* ARM64EAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1E2C3D2240D2F600F6B729 /* ARM64EAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    18731874                FE318FE01CAC982F00DFCC54 /* ECMAScriptSpecInternalFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = FE318FDE1CAC8C5300DFCC54 /* ECMAScriptSpecInternalFunctions.h */; };
    18741875                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, ); }; };
    18761876                FE3842332324D51B009DD445 /* OptionsList.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3842312324D51B009DD445 /* OptionsList.h */; settings = {ATTRIBUTES = (Private, ); }; };
    18771877                FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */ = {isa = PBXBuildFile; fileRef = FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    50745074                FE35C2FB21B1E6C7000F4CA8 /* OpcodeGroup.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = OpcodeGroup.rb; sourceTree = "<group>"; };
    50755075                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>"; };
    50775076                FE3842312324D51B009DD445 /* OptionsList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionsList.h; sourceTree = "<group>"; };
    50785077                FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDollarVM.cpp; sourceTree = "<group>"; };
     
    73837382                                F692A8770255597D01FF60F7 /* Operations.cpp */,
    73847383                                F692A8780255597D01FF60F7 /* Operations.h */,
    7385                                 FE3842302324D51A009DD445 /* OptionEntry.h */,
    73867384                                0FE228EA1436AB2300196C48 /* Options.cpp */,
    73877385                                0FE228EB1436AB2300196C48 /* Options.h */,
     
    99069904                                A70447EA17A0BD4600F5898E /* OperandsInlines.h in Headers */,
    99079905                                BC18C4480E16F5CD00B34460 /* Operations.h in Headers */,
    9908                                 FE3842322324D51B009DD445 /* OptionEntry.h in Headers */,
    99099906                                0FE228ED1436AB2700196C48 /* Options.h in Headers */,
    99109907                                FE3842332324D51B009DD445 /* OptionsList.h in Headers */,
     
    1113511132                                536B315C1F71C5990037FC33 /* UnifiedSource88.cpp in Sources */,
    1113611133                                536B31621F71C5990037FC33 /* UnifiedSource89.cpp in Sources */,
     11134                                FE1D6D4523580E1F007A5C26 /* Options.cpp in Sources */,
    1113711135                                536B31421F71C5990037FC33 /* UnifiedSource90.cpp in Sources */,
    1113811136                                536B31491F71C5990037FC33 /* UnifiedSource91.cpp in Sources */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r251036 r251226  
    905905runtime/ObjectToStringAdaptiveStructureWatchpoint.cpp
    906906runtime/Operations.cpp
    907 runtime/Options.cpp
     907runtime/Options.cpp @no-unify
    908908runtime/ProgramExecutable.cpp
    909909runtime/PromiseDeferredTimer.cpp
  • trunk/Source/JavaScriptCore/runtime/JSCConfig.h

    r250559 r251226  
    2626#pragma once
    2727
    28 #include "OptionEntry.h"
    2928#include "OptionsList.h"
    3029#include <wtf/StdLibExtras.h>
     
    3736#if CPU(ARM64) || PLATFORM(WATCHOS)
    3837constexpr size_t PageSize = 16 * KB;
     38constexpr size_t ConfigSizeToProtect = 1 * PageSize;
    3939#else
    4040constexpr size_t PageSize = 4 * KB;
     41constexpr size_t ConfigSizeToProtect = 1 * PageSize;
    4142#endif
    42 
    43 constexpr size_t ConfigSizeToProtect = 32 * KB;
    4443
    4544#if ENABLE(SEPARATED_WX_HEAP)
     
    8382#endif
    8483
    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];
    87107        };
    88108        char ensureSize[ConfigSizeToProtect];
  • trunk/Source/JavaScriptCore/runtime/Options.cpp

    r250285 r251226  
    133133}
    134134
    135 bool Options::isAvailable(Options::ID id, Options::Availability availability)
     135bool Options::isAvailable(OptionID id, Options::Availability availability)
    136136{
    137137    if (availability == Availability::Restricted)
     
    141141    UNUSED_PARAM(id);
    142142#if !defined(NDEBUG)
    143     if (id == maxSingleAllocationSizeID)
     143    if (id == OptionID::maxSingleAllocationSize)
    144144        return true;
    145145#endif
    146146#if OS(DARWIN)
    147     if (id == useSigillCrashAnalyzerID)
     147    if (id == OptionID::useSigillCrashAnalyzer)
    148148        return true;
    149149#endif
    150150#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)
    155155        return !!LLINT_TRACING;
    156     if (id == traceLLIntSlowPathID)
     156    if (id == OptionID::traceLLIntSlowPath)
    157157        return !!LLINT_TRACING;
    158158    return false;
     
    160160
    161161template<typename T>
    162 bool overrideOptionWithHeuristic(T& variable, Options::ID id, const char* name, Options::Availability availability)
     162bool overrideOptionWithHeuristic(T& variable, OptionID id, const char* name, Options::Availability availability)
    163163{
    164164    bool available = (availability == Options::Availability::Normal)
     
    283283}
    284284
     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
     291template<OptionTypeID type, OptionID id>
     292constexpr 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
    285320// Realize the names for each of the options:
    286 const Options::EntryInfo Options::s_optionsInfo[Options::numberOfOptions] = {
     321const Options::EntryInfo Options::s_optionsInfo[NumberOfOptions] = {
    287322#define FILL_OPTION_INFO(type_, name_, defaultValue_, availability_, description_) \
    288     { #name_, description_, Options::Type::type_, Availability::availability_ },
     323    { #name_, description_, OptionTypeID::type_, Availability::availability_, optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>() },
    289324    FOR_EACH_JSC_OPTION(FILL_OPTION_INFO)
    290325#undef FILL_OPTION_INFO
     
    300335
    301336    struct OptionToScale {
    302         Options::ID id;
     337        size_t index;
    303338        int32_t minVal;
    304339    };
    305340
    306341    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 },
    314349    };
    315350
    316     const int numberOfOptionsToScale = sizeof(optionsToScale) / sizeof(OptionToScale);
     351    constexpr int numberOfOptionsToScale = sizeof(optionsToScale) / sizeof(OptionToScale);
    317352    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);
    322356    }
    323357}
     
    442476        Options::collectContinuously() = false;
    443477
    444     if (Option(Options::jitPolicyScaleID).isOverridden())
     478    if (Option(OptionID::jitPolicyScale).isOverridden())
    445479        scaleJITPolicy();
    446480   
     
    523557#endif
    524558            // 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            }
    528564            FOR_EACH_JSC_OPTION(INIT_OPTION)
    529565#undef INIT_OPTION
     
    549585#else // PLATFORM(COCOA)
    550586#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_);
    552588            FOR_EACH_JSC_OPTION(OVERRIDE_OPTION_WITH_HEURISTICS)
    553589#undef OVERRIDE_OPTION_WITH_HEURISTICS
     
    728764    const char* valueStr = equalStr + 1;
    729765
    730     // For each option, check if the specify arg is a match. If so, set the arg
     766    // For each option, check if the specified arg is a match. If so, set the arg
    731767    // if the value makes sense. Otherwise, move on to checking the next option.
    732768#define SET_OPTION_IF_MATCH(type_, name_, defaultValue_, availability_, description_) \
    733769    if (strlen(#name_) == static_cast<size_t>(equalStr - arg)      \
    734770        && !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_)) \
    737773            return false;                                          \
    738         OptionEntry::type_ value;                                  \
    739         value = (defaultValue_);                                   \
     774        OptionTypes::type_ value;                                  \
    740775        bool success = parse(valueStr, value);                     \
    741776        if (success) {                                             \
     
    817852    }
    818853
    819     for (int id = 0; id < numberOfOptions; id++) {
     854    for (size_t id = 0; id < NumberOfOptions; id++) {
    820855        if (separator && id)
    821856            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);
    823858    }
    824859}
     
    836871}
    837872
    838 void Options::dumpOption(StringBuilder& builder, DumpLevel level, Options::ID id,
     873void Options::dumpOption(StringBuilder& builder, DumpLevel level, OptionID id,
    839874    const char* header, const char* footer, DumpDefaultsOption dumpDefaultsOption)
    840875{
    841     if (id >= numberOfOptions)
     876    if (static_cast<size_t>(id) >= NumberOfOptions)
    842877        return; // Illegal option.
    843878
     
    881916}
    882917
     918Option::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
     938const 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
    883960void Option::dump(StringBuilder& builder) const
    884961{
    885962    switch (type()) {
    886     case Options::Type::Bool:
    887         builder.append(m_entry.valBool ? "true" : "false");
     963    case OptionTypeID::Bool:
     964        builder.append(m_valBool ? "true" : "false");
    888965        break;
    889     case Options::Type::Unsigned:
    890         builder.appendNumber(m_entry.valUnsigned);
     966    case OptionTypeID::Unsigned:
     967        builder.appendNumber(m_valUnsigned);
    891968        break;
    892     case Options::Type::Size:
    893         builder.appendNumber(m_entry.valSize);
     969    case OptionTypeID::Size:
     970        builder.appendNumber(m_valSize);
    894971        break;
    895     case Options::Type::Double:
    896         builder.appendFixedPrecisionNumber(m_entry.valDouble);
     972    case OptionTypeID::Double:
     973        builder.appendFixedPrecisionNumber(m_valDouble);
    897974        break;
    898     case Options::Type::Int32:
    899         builder.appendNumber(m_entry.valInt32);
     975    case OptionTypeID::Int32:
     976        builder.appendNumber(m_valInt32);
    900977        break;
    901     case Options::Type::OptionRange:
    902         builder.append(m_entry.valOptionRange.rangeString());
     978    case OptionTypeID::OptionRange:
     979        builder.append(m_valOptionRange.rangeString());
    903980        break;
    904     case Options::Type::OptionString: {
    905         const char* option = m_entry.valOptionString;
     981    case OptionTypeID::OptionString: {
     982        const char* option = m_valOptionString;
    906983        if (!option)
    907984            option = "";
     
    911988        break;
    912989    }
    913     case Options::Type::GCLogLevel: {
    914         builder.append(GCLogging::levelAsString(m_entry.valGCLogLevel));
     990    case OptionTypeID::GCLogLevel: {
     991        builder.append(GCLogging::levelAsString(m_valGCLogLevel));
    915992        break;
    916993    }
     
    921998{
    922999    switch (type()) {
    923     case Options::Type::Bool:
    924         return m_entry.valBool == other.m_entry.valBool;
    925     case Options::Type::Unsigned:
    926         return m_entry.valUnsigned == other.m_entry.valUnsigned;
    927     case Options::Type::Size:
    928         return m_entry.valSize == other.m_entry.valSize;
    929     case Options::Type::Double:
    930         return (m_entry.valDouble == other.m_entry.valDouble) || (std::isnan(m_entry.valDouble) && std::isnan(other.m_entry.valDouble));
    931     case Options::Type::Int32:
    932         return m_entry.valInt32 == other.m_entry.valInt32;
    933     case Options::Type::OptionRange:
    934         return m_entry.valOptionRange.rangeString() == other.m_entry.valOptionRange.rangeString();
    935     case Options::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 Options::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;
    9401017    }
    9411018    return false;
  • trunk/Source/JavaScriptCore/runtime/Options.h

    r250278 r251226  
    3030#include <stdint.h>
    3131#include <stdio.h>
    32 #include <wtf/PrintStream.h>
    3332#include <wtf/StdLibExtras.h>
    3433
     
    5453class Options {
    5554public:
    56     enum class DumpLevel {
     55    enum class DumpLevel : uint8_t {
    5756        None = 0,
    5857        Overridden,
     
    6160    };
    6261
    63     enum class Availability {
     62    enum class Availability : uint8_t {
    6463        Normal = 0,
    6564        Restricted,
     
    6766    };
    6867
    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         numberOfOptions
    75     };
    76 #undef DECLARE_OPTION_ID
    77 
    78     enum class Type {
    79         Bool,
    80         Unsigned,
    81         Double,
    82         Int32,
    83         Size,
    84         OptionRange,
    85         OptionString,
    86         GCLogLevel,
    87     };
    88 
    8968    JS_EXPORT_PRIVATE static void initialize();
    9069
     
    10281    JS_EXPORT_PRIVATE static void ensureOptionsAreCoherent();
    10382
     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
    10491#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();
    10894    FOR_EACH_JSC_OPTION(DECLARE_OPTION_ACCESSORS)
    10995#undef DECLARE_OPTION_ACCESSORS
    11096
    111     static bool isAvailable(ID, Availability);
     97    static bool isAvailable(OptionID, Availability);
    11298
    11399private:
     
    117103        const char* name;
    118104        const char* description;
    119         Type type;
     105        OptionTypeID type;
    120106        Availability availability;
     107        unsigned typeSpecificIndex;
    121108    };
    122109
     
    130117    static void dumpAllOptions(StringBuilder&, DumpLevel, const char* title,
    131118        const char* separator, const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
    132     static void dumpOption(StringBuilder&, DumpLevel, ID,
     119    static void dumpOption(StringBuilder&, DumpLevel, OptionID,
    133120        const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
    134121
     
    137124    static bool overrideAliasedOptionWithHeuristic(const char* name);
    138125
    139     static const EntryInfo s_optionsInfo[numberOfOptions];
     126    static const EntryInfo s_optionsInfo[NumberOfOptions];
    140127
    141128    friend class Option;
     
    144131class Option {
    145132public:
    146     Option(Options::ID id)
    147         : m_id(id)
    148         , m_entry(g_jscConfig.options[m_id])
    149     {
    150     }
    151    
     133    Option(OptionID);
     134
    152135    void dump(StringBuilder&) const;
    153136
     
    155138    bool operator!=(const Option& other) const { return !(*this == other); }
    156139   
    157     Options::ID id() const { return m_id; }
    158     const char* name() const;
    159     const char* description() const;
    160     Options::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(); }
    163146    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
    173153private:
    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
     175template<OptionTypeID type, OptionID id>
     176constexpr 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_>()]; \
    179198    }
    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)
    249203
    250204} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/OptionsList.h

    r250806 r251226  
    2626#pragma once
    2727
     28#include "GCLogging.h"
     29#include <wtf/PrintStream.h>
     30
    2831namespace JSC {
    2932
     
    3235// The FOR_EACH_JSC_OPTION() macro below defines a list of all JSC options in use,
    3336// along with their types and default values. The options values are actually
    34 // realized as an array of OptionEntry elements in JSC::Config.
     37// realized as arrays of each of the OptionTypes in JSC::Config.
    3538//
    36 //     Options::initialize() will initialize the array of options values with
     39//     Options::initialize() will initialize the arrays of options values with
    3740// the defaults specified in FOR_EACH_JSC_OPTION() below. After that, the values can
    3841// be programmatically read and written to using an accessor method with the
     
    5558// values after the sanity checks (for your own testing), then you're liable to
    5659// 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
     65class OptionRange {
     66private:
     67    enum RangeState { Uninitialized, InitError, Normal, Inverted };
     68public:
     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
     86private:
     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
     105namespace 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
     114enum 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};
    57122
    58123#define FOR_EACH_JSC_OPTION(v)                                          \
     
    511576    v(maximumInliningCallerSize, maximumInliningCallerBytecodeCost, SameOption) \
    512577
     578#define DECLARE_OPTION_ID(type_, name_, defaultValue_, availability_, description_) \
     579    name_,
     580enum class OptionID : uint16_t {
     581    FOR_EACH_JSC_OPTION(DECLARE_OPTION_ID)
     582};
     583#undef DECLARE_OPTION_ID
     584
     585static constexpr size_t InvalidOptionIndex = std::numeric_limits<size_t>::max();
    513586
    514587constexpr size_t countNumberOfJSCOptions()
     
    523596constexpr size_t NumberOfOptions = countNumberOfJSCOptions();
    524597
     598constexpr 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
     609constexpr size_t NumberOfBoolOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Bool);
     610constexpr size_t NumberOfUnsignedOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Unsigned);
     611constexpr size_t NumberOfDoubleOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Double);
     612constexpr size_t NumberOfInt32Options = countNumberOfJSCOptionsOfType(OptionTypeID::Int32);
     613constexpr size_t NumberOfSizeOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Size);
     614constexpr size_t NumberOfOptionRangeOptions = countNumberOfJSCOptionsOfType(OptionTypeID::OptionRange);
     615constexpr size_t NumberOfOptionStringOptions = countNumberOfJSCOptionsOfType(OptionTypeID::OptionString);
     616constexpr size_t NumberOfGCLogLevelOptions = countNumberOfJSCOptionsOfType(OptionTypeID::GCLogLevel);
     617
    525618} // namespace JSC
    526 
Note: See TracChangeset for help on using the changeset viewer.