Diff
Modified: trunk/Source/_javascript_Core/API/glib/JSCOptions.cpp (251225 => 251226)
--- trunk/Source/_javascript_Core/API/glib/JSCOptions.cpp 2019-10-17 03:03:59 UTC (rev 251225)
+++ trunk/Source/_javascript_Core/API/glib/JSCOptions.cpp 2019-10-17 05:45:58 UTC (rev 251226)
@@ -168,7 +168,7 @@
{
#define SET_OPTION_VALUE(type_, name_, defaultValue_, availability_, description_) \
if (!g_strcmp0(#name_, option)) { \
- OptionEntry::type_ valueToSet; \
+ OptionTypes::type_ valueToSet; \
if (!valueFromGValue(value, valueToSet)) \
return FALSE; \
Options::name_() = valueToSet; \
@@ -186,7 +186,7 @@
{
#define GET_OPTION_VALUE(type_, name_, defaultValue_, availability_, description_) \
if (!g_strcmp0(#name_, option)) { \
- OptionEntry::type_ valueToGet = Options::name_(); \
+ OptionTypes::type_ valueToGet = Options::name_(); \
valueToGValue(valueToGet, value); \
return TRUE; \
}
@@ -616,8 +616,8 @@
#define VISIT_OPTION(type_, name_, defaultValue_, availability_, description_) \
if (Options::Availability::availability_ == Options::Availability::Normal \
- || Options::isAvailable(Options::name_##ID, Options::Availability::availability_)) { \
- OptionEntry::type_ defaultValue { }; \
+ || Options::isAvailable(OptionID::name_, Options::Availability::availability_)) { \
+ OptionTypes::type_ defaultValue { }; \
auto optionType = jscOptionsType(defaultValue); \
if (function (#name_, optionType, description_, userData)) \
return; \
@@ -666,7 +666,7 @@
GArray* entries = g_array_new(TRUE, TRUE, sizeof(GOptionEntry));
#define REGISTER_OPTION(type_, name_, defaultValue_, availability_, description_) \
if (Options::Availability::availability_ == Options::Availability::Normal \
- || Options::isAvailable(Options::name_##ID, Options::Availability::availability_)) { \
+ || Options::isAvailable(OptionID::name_, Options::Availability::availability_)) { \
GUniquePtr<char> name(g_strdup_printf("jsc-%s", #name_)); \
entries = g_array_set_size(entries, entries->len + 1); \
GOptionEntry* entry = &g_array_index(entries, GOptionEntry, entries->len - 1); \
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (251225 => 251226)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2019-10-17 03:03:59 UTC (rev 251225)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2019-10-17 05:45:58 UTC (rev 251226)
@@ -920,7 +920,6 @@
runtime/ObjectInitializationScope.h
runtime/ObjectPrototype.h
runtime/Operations.h
- runtime/OptionEntry.h
runtime/Options.h
runtime/OptionsList.h
runtime/ParseInt.h
Modified: trunk/Source/_javascript_Core/ChangeLog (251225 => 251226)
--- trunk/Source/_javascript_Core/ChangeLog 2019-10-17 03:03:59 UTC (rev 251225)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-10-17 05:45:58 UTC (rev 251226)
@@ -1,3 +1,137 @@
+2019-10-16 Mark Lam <mark....@apple.com>
+
+ 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.
+
+ 2. Introduce the optionTypeSpecificIndex() constexpr template function for
+ computing the index of each option in their respective type specific options
+ array.
+
+ 3. 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.
+
+ 4. 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.
+
+ 5. Removed the large OptionEntry arrays from JSC::Config.
+ Added type specific options arrays.
+ Also ordered these arrays to maximize compactness and minimize internal fragmentation.
+
+ 6. 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.
+
+ 7. 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.
+
+ 8. 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:
+ * _javascript_Core.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):
+
2019-10-16 Keith Miller <keith_mil...@apple.com>
Move assert in Wasm::Plan::fail.
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (251225 => 251226)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2019-10-17 03:03:59 UTC (rev 251225)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2019-10-17 05:45:58 UTC (rev 251226)
@@ -1864,6 +1864,7 @@
FE1BD0211E72027900134BC9 /* CellProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1BD0201E72027000134BC9 /* CellProfile.h */; };
FE1BD0251E72053800134BC9 /* HeapVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1BD0231E72052F00134BC9 /* HeapVerifier.h */; };
FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1C0FFC1B193E9800B53FCA /* Exception.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ FE1D6D4523580E1F007A5C26 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; };
FE1E2C3F2240DD5800F6B729 /* MacroAssemblerARM64E.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1E2C3E2240D30B00F6B729 /* MacroAssemblerARM64E.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE1E2C402240DD6200F6B729 /* ARM64EAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1E2C3D2240D2F600F6B729 /* ARM64EAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = FE20CE9C15F04A9500DF3430 /* LLIntCLoop.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1872,7 +1873,6 @@
FE3022D71E42857300BAC493 /* VMInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3022D51E42856700BAC493 /* VMInspector.h */; };
FE318FE01CAC982F00DFCC54 /* ECMAScriptSpecInternalFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = FE318FDE1CAC8C5300DFCC54 /* ECMAScriptSpecInternalFunctions.h */; };
FE3422121D6B81C30032BE88 /* ThrowScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3422111D6B818C0032BE88 /* ThrowScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
- FE3842322324D51B009DD445 /* OptionEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3842302324D51A009DD445 /* OptionEntry.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE3842332324D51B009DD445 /* OptionsList.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3842312324D51B009DD445 /* OptionsList.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */ = {isa = PBXBuildFile; fileRef = FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE3A06A61C10B72D00390FDD /* JITBitOrGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3A06A41C10B70800390FDD /* JITBitOrGenerator.h */; };
@@ -5073,7 +5073,6 @@
FE35C2FA21B1E6C7000F4CA8 /* Options.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = Options.rb; sourceTree = "<group>"; };
FE35C2FB21B1E6C7000F4CA8 /* OpcodeGroup.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = OpcodeGroup.rb; sourceTree = "<group>"; };
FE35C2FC21B1E6C7000F4CA8 /* Metadata.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = Metadata.rb; sourceTree = "<group>"; };
- FE3842302324D51A009DD445 /* OptionEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionEntry.h; sourceTree = "<group>"; };
FE3842312324D51B009DD445 /* OptionsList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionsList.h; sourceTree = "<group>"; };
FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDollarVM.cpp; sourceTree = "<group>"; };
FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDollarVM.h; sourceTree = "<group>"; };
@@ -7382,7 +7381,6 @@
E39EEAF22281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h */,
F692A8770255597D01FF60F7 /* Operations.cpp */,
F692A8780255597D01FF60F7 /* Operations.h */,
- FE3842302324D51A009DD445 /* OptionEntry.h */,
0FE228EA1436AB2300196C48 /* Options.cpp */,
0FE228EB1436AB2300196C48 /* Options.h */,
FE3842312324D51B009DD445 /* OptionsList.h */,
@@ -9905,7 +9903,6 @@
0F2BDC2C151FDE9100CD8910 /* Operands.h in Headers */,
A70447EA17A0BD4600F5898E /* OperandsInlines.h in Headers */,
BC18C4480E16F5CD00B34460 /* Operations.h in Headers */,
- FE3842322324D51B009DD445 /* OptionEntry.h in Headers */,
0FE228ED1436AB2700196C48 /* Options.h in Headers */,
FE3842332324D51B009DD445 /* OptionsList.h in Headers */,
E356987222841187008CDCCB /* PackedCellPtr.h in Headers */,
@@ -11134,6 +11131,7 @@
536B314A1F71C5990037FC33 /* UnifiedSource87.cpp in Sources */,
536B315C1F71C5990037FC33 /* UnifiedSource88.cpp in Sources */,
536B31621F71C5990037FC33 /* UnifiedSource89.cpp in Sources */,
+ FE1D6D4523580E1F007A5C26 /* Options.cpp in Sources */,
536B31421F71C5990037FC33 /* UnifiedSource90.cpp in Sources */,
536B31491F71C5990037FC33 /* UnifiedSource91.cpp in Sources */,
536B31521F71C5990037FC33 /* UnifiedSource92.cpp in Sources */,
Modified: trunk/Source/_javascript_Core/Sources.txt (251225 => 251226)
--- trunk/Source/_javascript_Core/Sources.txt 2019-10-17 03:03:59 UTC (rev 251225)
+++ trunk/Source/_javascript_Core/Sources.txt 2019-10-17 05:45:58 UTC (rev 251226)
@@ -904,7 +904,7 @@
runtime/ObjectPrototype.cpp
runtime/ObjectToStringAdaptiveStructureWatchpoint.cpp
runtime/Operations.cpp
-runtime/Options.cpp
+runtime/Options.cpp @no-unify
runtime/ProgramExecutable.cpp
runtime/PromiseDeferredTimer.cpp
runtime/PropertyDescriptor.cpp
Modified: trunk/Source/_javascript_Core/runtime/JSCConfig.h (251225 => 251226)
--- trunk/Source/_javascript_Core/runtime/JSCConfig.h 2019-10-17 03:03:59 UTC (rev 251225)
+++ trunk/Source/_javascript_Core/runtime/JSCConfig.h 2019-10-17 05:45:58 UTC (rev 251226)
@@ -25,7 +25,6 @@
#pragma once
-#include "OptionEntry.h"
#include "OptionsList.h"
#include <wtf/StdLibExtras.h>
@@ -36,12 +35,12 @@
#if CPU(ARM64) || PLATFORM(WATCHOS)
constexpr size_t PageSize = 16 * KB;
+constexpr size_t ConfigSizeToProtect = 1 * PageSize;
#else
constexpr size_t PageSize = 4 * KB;
+constexpr size_t ConfigSizeToProtect = 1 * PageSize;
#endif
-constexpr size_t ConfigSizeToProtect = 32 * KB;
-
#if ENABLE(SEPARATED_WX_HEAP)
using JITWriteSeparateHeapsFunction = void (*)(off_t, const void*, size_t);
#endif
@@ -82,8 +81,29 @@
bool useFastPermisionsJITCopy;
#endif
- OptionEntry options[NumberOfOptions];
- OptionEntry defaultOptions[NumberOfOptions];
+ bool typeBoolOptions[NumberOfBoolOptions];
+ bool typeBoolDefaultOptions[NumberOfBoolOptions];
+
+ GCLogging::Level typeGCLogLevelOptions[NumberOfGCLogLevelOptions];
+ GCLogging::Level typeGCLogLevelDefaultOptions[NumberOfGCLogLevelOptions];
+
+ int32_t typeInt32Options[NumberOfInt32Options];
+ int32_t typeInt32DefaultOptions[NumberOfInt32Options];
+
+ unsigned typeUnsignedOptions[NumberOfUnsignedOptions];
+ unsigned typeUnsignedDefaultOptions[NumberOfUnsignedOptions];
+
+ double typeDoubleOptions[NumberOfDoubleOptions];
+ double typeDoubleDefaultOptions[NumberOfDoubleOptions];
+
+ size_t typeSizeOptions[NumberOfSizeOptions];
+ size_t typeSizeDefaultOptions[NumberOfSizeOptions];
+
+ const char* typeOptionStringOptions[NumberOfOptionStringOptions];
+ const char* typeOptionStringDefaultOptions[NumberOfOptionStringOptions];
+
+ OptionRange typeOptionRangeOptions[NumberOfOptionRangeOptions];
+ OptionRange typeOptionRangeDefaultOptions[NumberOfOptionRangeOptions];
};
char ensureSize[ConfigSizeToProtect];
};
Deleted: trunk/Source/_javascript_Core/runtime/OptionEntry.h (251225 => 251226)
--- trunk/Source/_javascript_Core/runtime/OptionEntry.h 2019-10-17 03:03:59 UTC (rev 251225)
+++ trunk/Source/_javascript_Core/runtime/OptionEntry.h 2019-10-17 05:45:58 UTC (rev 251226)
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include "GCLogging.h"
-#include <wtf/PrintStream.h>
-
-namespace JSC {
-
-class OptionRange {
-private:
- enum RangeState { Uninitialized, InitError, Normal, Inverted };
-public:
- OptionRange& operator= (const int& rhs)
- { // Only needed for initialization
- if (!rhs) {
- m_state = Uninitialized;
- m_rangeString = 0;
- m_lowLimit = 0;
- m_highLimit = 0;
- }
- return *this;
- }
-
- bool init(const char*);
- bool isInRange(unsigned);
- const char* rangeString() const { return (m_state > InitError) ? m_rangeString : s_nullRangeStr; }
-
- void dump(PrintStream& out) const;
-
-private:
- static const char* const s_nullRangeStr;
-
- RangeState m_state;
- const char* m_rangeString;
- unsigned m_lowLimit;
- unsigned m_highLimit;
-};
-
-// For storing for an option value:
-union OptionEntry {
- using Bool = bool;
- using Unsigned = unsigned;
- using Double = double;
- using Int32 = int32_t;
- using Size = size_t;
- using OptionRange = JSC::OptionRange;
- using OptionString = const char*;
- using GCLogLevel = GCLogging::Level;
-
- bool valBool;
- unsigned valUnsigned;
- double valDouble;
- int32_t valInt32;
- size_t valSize;
- OptionRange valOptionRange;
- const char* valOptionString;
- GCLogging::Level valGCLogLevel;
-};
-
-} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/Options.cpp (251225 => 251226)
--- trunk/Source/_javascript_Core/runtime/Options.cpp 2019-10-17 03:03:59 UTC (rev 251225)
+++ trunk/Source/_javascript_Core/runtime/Options.cpp 2019-10-17 05:45:58 UTC (rev 251226)
@@ -132,7 +132,7 @@
return false;
}
-bool Options::isAvailable(Options::ID id, Options::Availability availability)
+bool Options::isAvailable(OptionID id, Options::Availability availability)
{
if (availability == Availability::Restricted)
return g_jscConfig.restrictedOptionsEnabled;
@@ -140,26 +140,26 @@
UNUSED_PARAM(id);
#if !defined(NDEBUG)
- if (id == maxSingleAllocationSizeID)
+ if (id == OptionID::maxSingleAllocationSize)
return true;
#endif
#if OS(DARWIN)
- if (id == useSigillCrashAnalyzerID)
+ if (id == OptionID::useSigillCrashAnalyzer)
return true;
#endif
#if ENABLE(ASSEMBLER) && OS(LINUX)
- if (id == logJITCodeForPerfID)
+ if (id == OptionID::logJITCodeForPerf)
return true;
#endif
- if (id == traceLLIntExecutionID)
+ if (id == OptionID::traceLLIntExecution)
return !!LLINT_TRACING;
- if (id == traceLLIntSlowPathID)
+ if (id == OptionID::traceLLIntSlowPath)
return !!LLINT_TRACING;
return false;
}
template<typename T>
-bool overrideOptionWithHeuristic(T& variable, Options::ID id, const char* name, Options::Availability availability)
+bool overrideOptionWithHeuristic(T& variable, OptionID id, const char* name, Options::Availability availability)
{
bool available = (availability == Options::Availability::Normal)
|| Options::isAvailable(id, availability);
@@ -282,10 +282,45 @@
out.print(m_rangeString);
}
+// FIXME: This is a workaround for MSVC's inability to handle large sources.
+// Once the MSVC bug has been fixed, we can remove this snippet of code and
+// make its counterpart in Options.h unconditional.
+// See https://developercommunity.visualstudio.com/content/problem/653301/fatal-error-c1002-compiler-is-out-of-heap-space-in.html
+#if COMPILER(MSVC)
+
+template<OptionTypeID type, OptionID id>
+constexpr size_t optionTypeSpecificIndex()
+{
+ size_t index = 0;
+#define COUNT_INDEX_AND_FIND_MATCH(type_, name_, defaultValue_, availability_, description_) \
+ if (id == OptionID::name_) \
+ return index; \
+ if (type == OptionTypeID::type_) \
+ index++;
+
+ FOR_EACH_JSC_OPTION(COUNT_INDEX_AND_FIND_MATCH);
+#undef COUNT_INDEX_AND_FIND_MATCH
+ return InvalidOptionIndex;
+}
+
+#define DEFINE_OPTION_ACCESSORS(type_, name_, defaultValue_, availability_, description_) \
+ JS_EXPORT_PRIVATE OptionTypes::type_& Options::name_() \
+ { \
+ return g_jscConfig.type##type_##Options[optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>()]; \
+ } \
+ JS_EXPORT_PRIVATE OptionTypes::type_& Options::name_##Default() \
+ { \
+ return g_jscConfig.type##type_##DefaultOptions[optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>()]; \
+ }
+ FOR_EACH_JSC_OPTION(DEFINE_OPTION_ACCESSORS)
+#undef DEFINE_OPTION_ACCESSORS
+
+#endif // COMPILER(MSVC)
+
// Realize the names for each of the options:
-const Options::EntryInfo Options::s_optionsInfo[Options::numberOfOptions] = {
+const Options::EntryInfo Options::s_optionsInfo[NumberOfOptions] = {
#define FILL_OPTION_INFO(type_, name_, defaultValue_, availability_, description_) \
- { #name_, description_, Options::Type::type_, Availability::availability_ },
+ { #name_, description_, OptionTypeID::type_, Availability::availability_, optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>() },
FOR_EACH_JSC_OPTION(FILL_OPTION_INFO)
#undef FILL_OPTION_INFO
};
@@ -299,26 +334,25 @@
scaleFactor = 0.0;
struct OptionToScale {
- Options::ID id;
+ size_t index;
int32_t minVal;
};
static const OptionToScale optionsToScale[] = {
- { Options::thresholdForJITAfterWarmUpID, 0 },
- { Options::thresholdForJITSoonID, 0 },
- { Options::thresholdForOptimizeAfterWarmUpID, 1 },
- { Options::thresholdForOptimizeAfterLongWarmUpID, 1 },
- { Options::thresholdForOptimizeSoonID, 1 },
- { Options::thresholdForFTLOptimizeSoonID, 2 },
- { Options::thresholdForFTLOptimizeAfterWarmUpID, 2 }
+ { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForJITAfterWarmUp>(), 0 },
+ { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForJITSoon>(), 0 },
+ { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForOptimizeAfterWarmUp>(), 1 },
+ { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForOptimizeAfterLongWarmUp>(), 1 },
+ { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForOptimizeSoon>(), 1 },
+ { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForFTLOptimizeSoon>(), 2 },
+ { optionTypeSpecificIndex<OptionTypeID::Int32, OptionID::thresholdForFTLOptimizeAfterWarmUp>(), 2 },
};
- const int numberOfOptionsToScale = sizeof(optionsToScale) / sizeof(OptionToScale);
+ constexpr int numberOfOptionsToScale = sizeof(optionsToScale) / sizeof(OptionToScale);
for (int i = 0; i < numberOfOptionsToScale; i++) {
- Option option(optionsToScale[i].id);
- ASSERT(option.type() == Options::Type::Int32);
- option.int32Val() *= scaleFactor;
- option.int32Val() = std::max(option.int32Val(), optionsToScale[i].minVal);
+ int32_t& optionValue = g_jscConfig.typeInt32Options[optionsToScale[i].index];
+ optionValue *= scaleFactor;
+ optionValue = std::max(optionValue, optionsToScale[i].minVal);
}
}
@@ -441,7 +475,7 @@
if (!Options::useConcurrentGC())
Options::collectContinuously() = false;
- if (Option(Options::jitPolicyScaleID).isOverridden())
+ if (Option(OptionID::jitPolicyScale).isOverridden())
scaleJITPolicy();
if (Options::forceEagerCompilation()) {
@@ -522,9 +556,11 @@
Config::enableRestrictedOptions();
#endif
// Initialize each of the options with their default values:
-#define INIT_OPTION(type_, name_, defaultValue_, availability_, description_) \
- name_() = defaultValue_; \
- name_##Default() = defaultValue_;
+#define INIT_OPTION(type_, name_, defaultValue_, availability_, description_) { \
+ auto value = defaultValue_; \
+ name_() = value; \
+ name_##Default() = value; \
+ }
FOR_EACH_JSC_OPTION(INIT_OPTION)
#undef INIT_OPTION
@@ -548,7 +584,7 @@
CRASH();
#else // PLATFORM(COCOA)
#define OVERRIDE_OPTION_WITH_HEURISTICS(type_, name_, defaultValue_, availability_, description_) \
- overrideOptionWithHeuristic(name_(), name_##ID, "JSC_" #name_, Availability::availability_);
+ overrideOptionWithHeuristic(name_(), OptionID::name_, "JSC_" #name_, Availability::availability_);
FOR_EACH_JSC_OPTION(OVERRIDE_OPTION_WITH_HEURISTICS)
#undef OVERRIDE_OPTION_WITH_HEURISTICS
#endif // PLATFORM(COCOA)
@@ -727,16 +763,15 @@
const char* valueStr = equalStr + 1;
- // For each option, check if the specify arg is a match. If so, set the arg
+ // For each option, check if the specified arg is a match. If so, set the arg
// if the value makes sense. Otherwise, move on to checking the next option.
#define SET_OPTION_IF_MATCH(type_, name_, defaultValue_, availability_, description_) \
if (strlen(#name_) == static_cast<size_t>(equalStr - arg) \
&& !strncmp(arg, #name_, equalStr - arg)) { \
- if (Availability::availability_ != Availability::Normal \
- && !isAvailable(name_##ID, Availability::availability_)) \
+ if (Availability::availability_ != Availability::Normal \
+ && !isAvailable(OptionID::name_, Availability::availability_)) \
return false; \
- OptionEntry::type_ value; \
- value = (defaultValue_); \
+ OptionTypes::type_ value; \
bool success = parse(valueStr, value); \
if (success) { \
name_() = value; \
@@ -816,10 +851,10 @@
builder.append('\n');
}
- for (int id = 0; id < numberOfOptions; id++) {
+ for (size_t id = 0; id < NumberOfOptions; id++) {
if (separator && id)
builder.append(separator);
- dumpOption(builder, level, static_cast<ID>(id), optionHeader, optionFooter, dumpDefaultsOption);
+ dumpOption(builder, level, static_cast<OptionID>(id), optionHeader, optionFooter, dumpDefaultsOption);
}
}
@@ -835,10 +870,10 @@
fprintf(stream, "%s", builder.toString().utf8().data());
}
-void Options::dumpOption(StringBuilder& builder, DumpLevel level, Options::ID id,
+void Options::dumpOption(StringBuilder& builder, DumpLevel level, OptionID id,
const char* header, const char* footer, DumpDefaultsOption dumpDefaultsOption)
{
- if (id >= numberOfOptions)
+ if (static_cast<size_t>(id) >= NumberOfOptions)
return; // Illegal option.
Option option(id);
@@ -880,29 +915,71 @@
CRASH();
}
+Option::Option(OptionID id)
+ : m_id(id)
+{
+ unsigned index = static_cast<unsigned>(m_id);
+ unsigned typeSpecificIndex = Options::s_optionsInfo[index].typeSpecificIndex;
+ OptionTypeID type = Options::s_optionsInfo[index].type;
+
+ switch (type) {
+
+#define HANDLE_CASE(OptionType_, type_) \
+ case OptionTypeID::OptionType_: \
+ ASSERT(typeSpecificIndex < NumberOf##OptionType_##Options); \
+ m_val##OptionType_ = g_jscConfig.type##OptionType_##Options[typeSpecificIndex]; \
+ break;
+
+ FOR_EACH_JSC_OPTION_TYPE(HANDLE_CASE)
+#undef HANDLE_CASE
+ }
+}
+
+const Option Option::defaultOption() const
+{
+ Option result;
+ unsigned index = static_cast<unsigned>(m_id);
+ unsigned typeSpecificIndex = Options::s_optionsInfo[index].typeSpecificIndex;
+ OptionTypeID type = Options::s_optionsInfo[index].type;
+
+ result.m_id = m_id;
+ switch (type) {
+
+#define HANDLE_CASE(OptionType_, type_) \
+ case OptionTypeID::OptionType_: \
+ ASSERT(typeSpecificIndex < NumberOf##OptionType_##Options); \
+ result.m_val##OptionType_ = g_jscConfig.type##OptionType_##DefaultOptions[typeSpecificIndex]; \
+ break;
+
+ FOR_EACH_JSC_OPTION_TYPE(HANDLE_CASE)
+#undef HANDLE_CASE
+ }
+ return result;
+}
+
void Option::dump(StringBuilder& builder) const
{
switch (type()) {
- case Options::Type::Bool:
- builder.append(m_entry.valBool ? "true" : "false");
+ case OptionTypeID::Bool:
+ builder.append(m_valBool ? "true" : "false");
break;
- case Options::Type::Unsigned:
- builder.appendNumber(m_entry.valUnsigned);
+ case OptionTypeID::Unsigned:
+ builder.appendNumber(m_valUnsigned);
break;
- case Options::Type::Size:
- builder.appendNumber(m_entry.valSize);
+ case OptionTypeID::Size:
+ builder.appendNumber(m_valSize);
break;
- case Options::Type::Double:
- builder.appendFixedPrecisionNumber(m_entry.valDouble);
+ case OptionTypeID::Double:
+ builder.appendFixedPrecisionNumber(m_valDouble);
break;
- case Options::Type::Int32:
- builder.appendNumber(m_entry.valInt32);
+ case OptionTypeID::Int32:
+ builder.appendNumber(m_valInt32);
break;
- case Options::Type::OptionRange:
- builder.append(m_entry.valOptionRange.rangeString());
+ case OptionTypeID::OptionRange:
+ builder.append(m_valOptionRange.rangeString());
break;
- case Options::Type::OptionString: {
- const char* option = m_entry.valOptionString;
+ case OptionTypeID::OptionString: {
+ const char* option = m_valOptionString;
if (!option)
option = "";
builder.append('"');
@@ -910,8 +987,8 @@
builder.append('"');
break;
}
- case Options::Type::GCLogLevel: {
- builder.append(GCLogging::levelAsString(m_entry.valGCLogLevel));
+ case OptionTypeID::GCLogLevel: {
+ builder.append(GCLogging::levelAsString(m_valGCLogLevel));
break;
}
}
@@ -920,23 +997,23 @@
bool Option::operator==(const Option& other) const
{
switch (type()) {
- case Options::Type::Bool:
- return m_entry.valBool == other.m_entry.valBool;
- case Options::Type::Unsigned:
- return m_entry.valUnsigned == other.m_entry.valUnsigned;
- case Options::Type::Size:
- return m_entry.valSize == other.m_entry.valSize;
- case Options::Type::Double:
- return (m_entry.valDouble == other.m_entry.valDouble) || (std::isnan(m_entry.valDouble) && std::isnan(other.m_entry.valDouble));
- case Options::Type::Int32:
- return m_entry.valInt32 == other.m_entry.valInt32;
- case Options::Type::OptionRange:
- return m_entry.valOptionRange.rangeString() == other.m_entry.valOptionRange.rangeString();
- case Options::Type::OptionString:
- return (m_entry.valOptionString == other.m_entry.valOptionString)
- || (m_entry.valOptionString && other.m_entry.valOptionString && !strcmp(m_entry.valOptionString, other.m_entry.valOptionString));
- case Options::Type::GCLogLevel:
- return m_entry.valGCLogLevel == other.m_entry.valGCLogLevel;
+ case OptionTypeID::Bool:
+ return m_valBool == other.m_valBool;
+ case OptionTypeID::Unsigned:
+ return m_valUnsigned == other.m_valUnsigned;
+ case OptionTypeID::Size:
+ return m_valSize == other.m_valSize;
+ case OptionTypeID::Double:
+ return (m_valDouble == other.m_valDouble) || (std::isnan(m_valDouble) && std::isnan(other.m_valDouble));
+ case OptionTypeID::Int32:
+ return m_valInt32 == other.m_valInt32;
+ case OptionTypeID::OptionRange:
+ return m_valOptionRange.rangeString() == other.m_valOptionRange.rangeString();
+ case OptionTypeID::OptionString:
+ return (m_valOptionString == other.m_valOptionString)
+ || (m_valOptionString && other.m_valOptionString && !strcmp(m_valOptionString, other.m_valOptionString));
+ case OptionTypeID::GCLogLevel:
+ return m_valGCLogLevel == other.m_valGCLogLevel;
}
return false;
}
Modified: trunk/Source/_javascript_Core/runtime/Options.h (251225 => 251226)
--- trunk/Source/_javascript_Core/runtime/Options.h 2019-10-17 03:03:59 UTC (rev 251225)
+++ trunk/Source/_javascript_Core/runtime/Options.h 2019-10-17 05:45:58 UTC (rev 251226)
@@ -29,7 +29,6 @@
#include "JSExportMacros.h"
#include <stdint.h>
#include <stdio.h>
-#include <wtf/PrintStream.h>
#include <wtf/StdLibExtras.h>
namespace WTF {
@@ -53,7 +52,7 @@
class Options {
public:
- enum class DumpLevel {
+ enum class DumpLevel : uint8_t {
None = 0,
Overridden,
All,
@@ -60,32 +59,12 @@
Verbose
};
- enum class Availability {
+ enum class Availability : uint8_t {
Normal = 0,
Restricted,
Configurable
};
-#define DECLARE_OPTION_ID(type_, name_, defaultValue_, availability_, description_) \
- name_##ID,
-
- enum ID {
- FOR_EACH_JSC_OPTION(DECLARE_OPTION_ID)
- numberOfOptions
- };
-#undef DECLARE_OPTION_ID
-
- enum class Type {
- Bool,
- Unsigned,
- Double,
- Int32,
- Size,
- OptionRange,
- OptionString,
- GCLogLevel,
- };
-
JS_EXPORT_PRIVATE static void initialize();
// Parses a string of options where each option is of the format "--<optionName>=<value>"
@@ -101,14 +80,21 @@
JS_EXPORT_PRIVATE static void ensureOptionsAreCoherent();
+// FIXME: This is a workaround for MSVC's inability to handle large sources.
+// See https://developercommunity.visualstudio.com/content/problem/653301/fatal-error-c1002-compiler-is-out-of-heap-space-in.html
+#if COMPILER(MSVC)
+#define OPTION_ACCESSOR_LINKAGE JS_EXPORT_PRIVATE
+#else
+#define OPTION_ACCESSOR_LINKAGE ALWAYS_INLINE
+#endif
+
#define DECLARE_OPTION_ACCESSORS(type_, name_, defaultValue_, availability_, description_) \
- ALWAYS_INLINE static OptionEntry::type_& name_() { return g_jscConfig.options[name_##ID].val##type_; } \
- ALWAYS_INLINE static OptionEntry::type_& name_##Default() { return g_jscConfig.defaultOptions[name_##ID].val##type_; }
-
+ OPTION_ACCESSOR_LINKAGE static OptionTypes::type_& name_(); \
+ OPTION_ACCESSOR_LINKAGE static OptionTypes::type_& name_##Default();
FOR_EACH_JSC_OPTION(DECLARE_OPTION_ACCESSORS)
#undef DECLARE_OPTION_ACCESSORS
- static bool isAvailable(ID, Availability);
+ static bool isAvailable(OptionID, Availability);
private:
@@ -116,8 +102,9 @@
struct EntryInfo {
const char* name;
const char* description;
- Type type;
+ OptionTypeID type;
Availability availability;
+ unsigned typeSpecificIndex;
};
Options();
@@ -129,7 +116,7 @@
static void dumpOptionsIfNeeded();
static void dumpAllOptions(StringBuilder&, DumpLevel, const char* title,
const char* separator, const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
- static void dumpOption(StringBuilder&, DumpLevel, ID,
+ static void dumpOption(StringBuilder&, DumpLevel, OptionID,
const char* optionHeader, const char* optionFooter, DumpDefaultsOption);
static bool setOptionWithoutAlias(const char* arg);
@@ -136,7 +123,7 @@
static bool setAliasedOption(const char* arg);
static bool overrideAliasedOptionWithHeuristic(const char* name);
- static const EntryInfo s_optionsInfo[numberOfOptions];
+ static const EntryInfo s_optionsInfo[NumberOfOptions];
friend class Option;
};
@@ -143,108 +130,75 @@
class Option {
public:
- Option(Options::ID id)
- : m_id(id)
- , m_entry(g_jscConfig.options[m_id])
- {
- }
-
+ Option(OptionID);
+
void dump(StringBuilder&) const;
bool operator==(const Option& other) const;
bool operator!=(const Option& other) const { return !(*this == other); }
- Options::ID id() const { return m_id; }
- const char* name() const;
- const char* description() const;
- Options::Type type() const;
- Options::Availability availability() const;
- bool isOverridden() const;
+ OptionID id() const { return m_id; }
+ const char* name() const { return Options::s_optionsInfo[idIndex()].name; }
+ const char* description() const { return Options::s_optionsInfo[idIndex()].description; }
+ OptionTypeID type() const { return Options::s_optionsInfo[idIndex()].type; }
+ Options::Availability availability() const { return Options::s_optionsInfo[idIndex()].availability; }
+ bool isOverridden() const { return *this != defaultOption(); }
const Option defaultOption() const;
-
- bool& boolVal();
- unsigned& unsignedVal();
- double& doubleVal();
- int32_t& int32Val();
- OptionRange optionRangeVal();
- const char* optionStringVal();
- GCLogging::Level& gcLogLevelVal();
-
-private:
- // Only used for constructing default Options.
- Option(Options::ID id, OptionEntry& entry)
- : m_id(id)
- , m_entry(entry)
- {
- }
-
- Options::ID m_id;
- OptionEntry& m_entry;
-};
-inline const char* Option::name() const
-{
- return Options::s_optionsInfo[m_id].name;
-}
+#define DECLARE_ACCESSOR(OptionType_, type_) \
+ type_ val##OptionType_() const { return m_val##OptionType_; }
+ FOR_EACH_JSC_OPTION_TYPE(DECLARE_ACCESSOR)
+#undef DECLARE_ACCESSOR
-inline const char* Option::description() const
-{
- return Options::s_optionsInfo[m_id].description;
-}
+private:
+ Option() { }
-inline Options::Type Option::type() const
-{
- return Options::s_optionsInfo[m_id].type;
-}
+ size_t idIndex() const { return static_cast<size_t>(m_id); }
-inline Options::Availability Option::availability() const
-{
- return Options::s_optionsInfo[m_id].availability;
-}
+ OptionID m_id;
+ union {
-inline bool Option::isOverridden() const
-{
- return *this != defaultOption();
-}
+#define DECLARE_MEMBER(OptionType_, type_) \
+ type_ m_val##OptionType_;
+ FOR_EACH_JSC_OPTION_TYPE(DECLARE_MEMBER)
+#undef DECLARE_MEMBER
-inline const Option Option::defaultOption() const
-{
- return Option(m_id, g_jscConfig.defaultOptions[m_id]);
-}
+ };
+};
-inline bool& Option::boolVal()
-{
- return m_entry.valBool;
-}
+// FIXME: This is a workaround for MSVC's inability to handle large sources.
+// Once the MSVC bug has been fixed, we can make the following unconditional and
+// remove its counterpart MSVC version in Options.cpp.
+// See https://developercommunity.visualstudio.com/content/problem/653301/fatal-error-c1002-compiler-is-out-of-heap-space-in.html
+#if !COMPILER(MSVC)
-inline unsigned& Option::unsignedVal()
+template<OptionTypeID type, OptionID id>
+constexpr size_t optionTypeSpecificIndex()
{
- return m_entry.valUnsigned;
-}
+ size_t index = 0;
+#define COUNT_INDEX_AND_FIND_MATCH(type_, name_, defaultValue_, availability_, description_) \
+ if (id == OptionID::name_) \
+ return index; \
+ if (type == OptionTypeID::type_) \
+ index++;
-inline double& Option::doubleVal()
-{
- return m_entry.valDouble;
+ FOR_EACH_JSC_OPTION(COUNT_INDEX_AND_FIND_MATCH);
+#undef COUNT_INDEX_AND_FIND_MATCH
+ return InvalidOptionIndex;
}
-inline int32_t& Option::int32Val()
-{
- return m_entry.valInt32;
-}
+#define DEFINE_OPTION_ACCESSORS(type_, name_, defaultValue_, availability_, description_) \
+ ALWAYS_INLINE OptionTypes::type_& Options::name_() \
+ { \
+ return g_jscConfig.type##type_##Options[optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>()]; \
+ } \
+ ALWAYS_INLINE OptionTypes::type_& Options::name_##Default() \
+ { \
+ return g_jscConfig.type##type_##DefaultOptions[optionTypeSpecificIndex<OptionTypeID::type_, OptionID::name_>()]; \
+ }
+ FOR_EACH_JSC_OPTION(DEFINE_OPTION_ACCESSORS)
+#undef DEFINE_OPTION_ACCESSORS
-inline OptionRange Option::optionRangeVal()
-{
- return m_entry.valOptionRange;
-}
+#endif // !COMPILER(MSVC)
-inline const char* Option::optionStringVal()
-{
- return m_entry.valOptionString;
-}
-
-inline GCLogging::Level& Option::gcLogLevelVal()
-{
- return m_entry.valGCLogLevel;
-}
-
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/OptionsList.h (251225 => 251226)
--- trunk/Source/_javascript_Core/runtime/OptionsList.h 2019-10-17 03:03:59 UTC (rev 251225)
+++ trunk/Source/_javascript_Core/runtime/OptionsList.h 2019-10-17 05:45:58 UTC (rev 251226)
@@ -25,6 +25,9 @@
#pragma once
+#include "GCLogging.h"
+#include <wtf/PrintStream.h>
+
namespace JSC {
// How do JSC VM options work?
@@ -31,9 +34,9 @@
// ===========================
// The FOR_EACH_JSC_OPTION() macro below defines a list of all JSC options in use,
// along with their types and default values. The options values are actually
-// realized as an array of OptionEntry elements in JSC::Config.
+// realized as arrays of each of the OptionTypes in JSC::Config.
//
-// Options::initialize() will initialize the array of options values with
+// Options::initialize() will initialize the arrays of options values with
// the defaults specified in FOR_EACH_JSC_OPTION() below. After that, the values can
// be programmatically read and written to using an accessor method with the
// same name as the option. For example, the option "useJIT" can be read and
@@ -54,7 +57,69 @@
// checks are done after the option values are set. If you alter the option
// values after the sanity checks (for your own testing), then you're liable to
// ensure that the new values set are sane and reasonable for your own run.
+//
+// Any modifications to options must be done before the first VM is instantiate.
+// On instantiation of the first VM instance, the Options will be write protected
+// and cannot be modified thereafter.
+class OptionRange {
+private:
+ enum RangeState { Uninitialized, InitError, Normal, Inverted };
+public:
+ OptionRange& operator= (const int& rhs)
+ { // Only needed for initialization
+ if (!rhs) {
+ m_state = Uninitialized;
+ m_rangeString = 0;
+ m_lowLimit = 0;
+ m_highLimit = 0;
+ }
+ return *this;
+ }
+
+ bool init(const char*);
+ bool isInRange(unsigned);
+ const char* rangeString() const { return (m_state > InitError) ? m_rangeString : s_nullRangeStr; }
+
+ void dump(PrintStream& out) const;
+
+private:
+ static const char* const s_nullRangeStr;
+
+ RangeState m_state;
+ const char* m_rangeString;
+ unsigned m_lowLimit;
+ unsigned m_highLimit;
+};
+
+#define FOR_EACH_JSC_OPTION_TYPE(v) \
+ v(Bool, bool) \
+ v(Unsigned, unsigned) \
+ v(Double, double) \
+ v(Int32, int32_t) \
+ v(Size, size_t) \
+ v(OptionRange, OptionRange) \
+ v(OptionString, const char*) \
+ v(GCLogLevel, GCLogging::Level) \
+
+namespace OptionTypes {
+
+#define DECLARE_TYPES(OptionType_, type_) \
+ using OptionType_ = type_;
+ FOR_EACH_JSC_OPTION_TYPE(DECLARE_TYPES)
+#undef DECLARE_TYPES
+
+} // namespace OptionTypes
+
+enum class OptionTypeID : uint8_t {
+
+#define DECLARE_TYPEID(OptionType_, type_) \
+ OptionType_,
+ FOR_EACH_JSC_OPTION_TYPE(DECLARE_TYPEID)
+#undef DECLARE_TYPEID
+
+};
+
#define FOR_EACH_JSC_OPTION(v) \
v(Bool, useKernTCSM, true, Normal, "Note: this needs to go before other options since they depend on this value.") \
v(Bool, validateOptions, false, Normal, "crashes if mis-typed JSC options were passed to the VM") \
@@ -510,7 +575,15 @@
v(maximumFTLCandidateInstructionCount, maximumFTLCandidateBytecodeCost, SameOption) \
v(maximumInliningCallerSize, maximumInliningCallerBytecodeCost, SameOption) \
+#define DECLARE_OPTION_ID(type_, name_, defaultValue_, availability_, description_) \
+ name_,
+enum class OptionID : uint16_t {
+ FOR_EACH_JSC_OPTION(DECLARE_OPTION_ID)
+};
+#undef DECLARE_OPTION_ID
+static constexpr size_t InvalidOptionIndex = std::numeric_limits<size_t>::max();
+
constexpr size_t countNumberOfJSCOptions()
{
#define COUNT_OPTION(type_, name_, defaultValue_, availability_, description_) count++;
@@ -522,5 +595,24 @@
constexpr size_t NumberOfOptions = countNumberOfJSCOptions();
+constexpr size_t countNumberOfJSCOptionsOfType(OptionTypeID type)
+{
+ size_t count = 0;
+#define COUNT_OPTION(type_, name_, defaultValue_, availability_, description_) \
+ if (type == OptionTypeID::type_) \
+ count++;
+ FOR_EACH_JSC_OPTION(COUNT_OPTION);
+#undef COUNT_OPTION
+ return count;
+}
+
+constexpr size_t NumberOfBoolOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Bool);
+constexpr size_t NumberOfUnsignedOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Unsigned);
+constexpr size_t NumberOfDoubleOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Double);
+constexpr size_t NumberOfInt32Options = countNumberOfJSCOptionsOfType(OptionTypeID::Int32);
+constexpr size_t NumberOfSizeOptions = countNumberOfJSCOptionsOfType(OptionTypeID::Size);
+constexpr size_t NumberOfOptionRangeOptions = countNumberOfJSCOptionsOfType(OptionTypeID::OptionRange);
+constexpr size_t NumberOfOptionStringOptions = countNumberOfJSCOptionsOfType(OptionTypeID::OptionString);
+constexpr size_t NumberOfGCLogLevelOptions = countNumberOfJSCOptionsOfType(OptionTypeID::GCLogLevel);
+
} // namespace JSC
-