Skip to content

Commit 1e901f3

Browse files
author
Mark Lam
committed
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>()]; } 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: * JavaScriptCore.xcodeproj/project.pbxproj: * runtime/JSCConfig.h: * runtime/OptionEntry.h: Removed. * runtime/Options.cpp: (JSC::Options::isAvailable): (JSC::overrideOptionWithHeuristic): (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::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::optionTypeSpecificIndex): (JSC::countNumberOfJSCOptionsOfType): Canonical link: https://commits.webkit.org/215726@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@250262 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent cca3638 commit 1e901f3

9 files changed

Lines changed: 415 additions & 293 deletions

File tree

‎Source/JavaScriptCore/API/glib/JSCOptions.cpp‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ static gboolean jscOptionsSetValue(const char* option, const GValue* value)
168168
{
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; \
174174
Options::name_() = valueToSet; \
@@ -186,7 +186,7 @@ static gboolean jscOptionsGetValue(const char* option, GValue* value)
186186
{
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; \
192192
}
@@ -616,8 +616,8 @@ void jsc_options_foreach(JSCOptionsFunc function, gpointer userData)
616616

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)) \
623623
return; \
@@ -666,7 +666,7 @@ GOptionGroup* jsc_options_get_option_group(void)
666666
GArray* entries = g_array_new(TRUE, TRUE, sizeof(GOptionEntry));
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); \
672672
GOptionEntry* entry = &g_array_index(entries, GOptionEntry, entries->len - 1); \

‎Source/JavaScriptCore/CMakeLists.txt‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,6 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS
919919
runtime/ObjectInitializationScope.h
920920
runtime/ObjectPrototype.h
921921
runtime/Operations.h
922-
runtime/OptionEntry.h
923922
runtime/Options.h
924923
runtime/OptionsList.h
925924
runtime/ParseInt.h

‎Source/JavaScriptCore/ChangeLog‎

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,125 @@
1+
2019-09-23 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+
2. Introduce the optionTypeSpecificIndex() constexpr template function for
39+
computing the index of each option in their respective type specific options
40+
array.
41+
42+
3. Introduce OptionTypes, OptionTypeID, and OptionID.
43+
44+
The OptionTypes namespace replaces OptionEntry as the container of option types.
45+
The OptionID enum class replaces Options::ID.
46+
The OptionTypeID enum class is new and is used together with OptionID in
47+
constexpr templates to compute the typeSpecificIndex of options.
48+
49+
4. Removed the OptionEntry struct and OptionEntry.h. After (1), this struct is
50+
only used in the Option class. We just moved the union of option types (that
51+
OptionEntry embeds) into the Option class.
52+
53+
Moved class OptionRange into OptionsList.h.
54+
55+
5. Removed the large OptionEntry arrays from JSC::Config.
56+
Added type specific options arrays.
57+
Also ordered these arrays to maximize compactness and minimize internal fragmentation.
58+
59+
6. Changed scaleJITPolicy() to go directly to g_jscConfig.typeInt32Options[]
60+
instead of going through the Option wrapper object. This allows us to simplify
61+
things and make the Option class a read only interface of options.
62+
63+
7. Changed Options::initialize() to only compute the option default value once.
64+
The default value specified in the OptionsList may not always be a constant.
65+
Sometimes, it is a function call.
66+
67+
8. The Option class now only gives read only access to the options.
68+
69+
The Option class' role is to provide an interface for reading an option at any
70+
given OptionID without first knowing about the type of the specific option.
71+
It is useful for iterating options, and is currently only used by
72+
Options::dumpOption().
73+
74+
Technically, we could merge all the Option class code into its single client.
75+
We opted not to do this because the amount of code is non-trivial, and the
76+
Option class does a good job of encapsulating this functionality.
77+
78+
* API/glib/JSCOptions.cpp:
79+
(jscOptionsSetValue):
80+
(jscOptionsGetValue):
81+
(jsc_options_foreach):
82+
(jsc_options_get_option_group):
83+
* CMakeLists.txt:
84+
* JavaScriptCore.xcodeproj/project.pbxproj:
85+
* runtime/JSCConfig.h:
86+
* runtime/OptionEntry.h: Removed.
87+
* runtime/Options.cpp:
88+
(JSC::Options::isAvailable):
89+
(JSC::overrideOptionWithHeuristic):
90+
(JSC::scaleJITPolicy):
91+
(JSC::recomputeDependentOptions):
92+
(JSC::Options::initialize):
93+
(JSC::Options::setOptionWithoutAlias):
94+
(JSC::Options::dumpAllOptions):
95+
(JSC::Options::dumpOption):
96+
(JSC::Option::Option):
97+
(JSC::Option::defaultOption const):
98+
(JSC::Option::dump const):
99+
(JSC::Option::operator== const):
100+
* runtime/Options.h:
101+
(JSC::Option::id const):
102+
(JSC::Option::name const):
103+
(JSC::Option::description const):
104+
(JSC::Option::type const):
105+
(JSC::Option::availability const):
106+
(JSC::Option::isOverridden const):
107+
(JSC::Option::Option):
108+
(JSC::Option::idIndex const):
109+
(JSC::Option::defaultOption const): Deleted.
110+
(JSC::Option::boolVal): Deleted.
111+
(JSC::Option::unsignedVal): Deleted.
112+
(JSC::Option::doubleVal): Deleted.
113+
(JSC::Option::int32Val): Deleted.
114+
(JSC::Option::optionRangeVal): Deleted.
115+
(JSC::Option::optionStringVal): Deleted.
116+
(JSC::Option::gcLogLevelVal): Deleted.
117+
* runtime/OptionsList.h:
118+
(JSC::OptionRange::operator= ):
119+
(JSC::OptionRange::rangeString const):
120+
(JSC::optionTypeSpecificIndex):
121+
(JSC::countNumberOfJSCOptionsOfType):
122+
1123
2019-09-23 Devin Rousso <drousso@apple.com>
2124

3125
Web Inspector: Canvas: show WebGPU shader pipelines

‎Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,7 +1872,6 @@
18721872
FE3022D71E42857300BAC493 /* VMInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3022D51E42856700BAC493 /* VMInspector.h */; };
18731873
FE318FE01CAC982F00DFCC54 /* ECMAScriptSpecInternalFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = FE318FDE1CAC8C5300DFCC54 /* ECMAScriptSpecInternalFunctions.h */; };
18741874
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, ); }; };
18761875
FE3842332324D51B009DD445 /* OptionsList.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3842312324D51B009DD445 /* OptionsList.h */; settings = {ATTRIBUTES = (Private, ); }; };
18771876
FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */ = {isa = PBXBuildFile; fileRef = FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */; settings = {ATTRIBUTES = (Private, ); }; };
18781877
FE3A06A61C10B72D00390FDD /* JITBitOrGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3A06A41C10B70800390FDD /* JITBitOrGenerator.h */; };
@@ -5070,7 +5069,6 @@
50705069
FE35C2FA21B1E6C7000F4CA8 /* Options.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = Options.rb; sourceTree = "<group>"; };
50715070
FE35C2FB21B1E6C7000F4CA8 /* OpcodeGroup.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = OpcodeGroup.rb; sourceTree = "<group>"; };
50725071
FE35C2FC21B1E6C7000F4CA8 /* Metadata.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = Metadata.rb; sourceTree = "<group>"; };
5073-
FE3842302324D51A009DD445 /* OptionEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionEntry.h; sourceTree = "<group>"; };
50745072
FE3842312324D51B009DD445 /* OptionsList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionsList.h; sourceTree = "<group>"; };
50755073
FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDollarVM.cpp; sourceTree = "<group>"; };
50765074
FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDollarVM.h; sourceTree = "<group>"; };
@@ -7370,7 +7368,6 @@
73707368
E39EEAF22281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h */,
73717369
F692A8770255597D01FF60F7 /* Operations.cpp */,
73727370
F692A8780255597D01FF60F7 /* Operations.h */,
7373-
FE3842302324D51A009DD445 /* OptionEntry.h */,
73747371
0FE228EA1436AB2300196C48 /* Options.cpp */,
73757372
0FE228EB1436AB2300196C48 /* Options.h */,
73767373
FE3842312324D51B009DD445 /* OptionsList.h */,
@@ -9353,7 +9350,6 @@
93539350
0FEA0A10170513DB00BB722C /* FTLLowerDFGToB3.h in Headers */,
93549351
A7D89D0217A0B90400773AD8 /* FTLLoweredNodeValue.h in Headers */,
93559352
0F2B9CF919D0BAC100B1D1B5 /* FTLOperations.h in Headers */,
9356-
FE3842322324D51B009DD445 /* OptionEntry.h in Headers */,
93579353
0FD8A31C17D51F2200CA2C40 /* FTLOSREntry.h in Headers */,
93589354
0F235BDD17178E1C00690C7F /* FTLOSRExit.h in Headers */,
93599355
0F235BE017178E1C00690C7F /* FTLOSRExitCompiler.h in Headers */,

‎Source/JavaScriptCore/runtime/JSCConfig.h‎

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
#pragma once
2727

28-
#include "OptionEntry.h"
2928
#include "OptionsList.h"
3029
#include <wtf/StdLibExtras.h>
3130

@@ -36,12 +35,15 @@ class FixedVMPoolExecutableAllocator;
3635

3736
#if CPU(ARM64) || PLATFORM(WATCHOS)
3837
constexpr size_t PageSize = 16 * KB;
39-
#else
38+
constexpr size_t ConfigSizeToProtect = 1 * PageSize;
39+
#elif CPU(X86_64) || CPU(X86)
4040
constexpr size_t PageSize = 4 * KB;
41+
constexpr size_t ConfigSizeToProtect = 1 * PageSize;
42+
#elif CPU(PPC64) || CPU(PPC64LE) || CPU(PPC) || CPU(UNKNOWN)
43+
constexpr size_t PageSize = 64 * KB;
44+
constexpr size_t ConfigSizeToProtect = 1 * PageSize;
4145
#endif
4246

43-
constexpr size_t ConfigSizeToProtect = 16 * KB;
44-
4547
#if ENABLE(SEPARATED_WX_HEAP)
4648
using JITWriteSeparateHeapsFunction = void (*)(off_t, const void*, size_t);
4749
#endif
@@ -82,8 +84,29 @@ struct Config {
8284
bool useFastPermisionsJITCopy;
8385
#endif
8486

85-
OptionEntry options[NumberOfOptions];
86-
OptionEntry defaultOptions[NumberOfOptions];
87+
bool typeBoolOptions[NumberOfBoolOptions];
88+
bool typeBoolDefaultOptions[NumberOfBoolOptions];
89+
90+
GCLogging::Level typeGCLogLevelOptions[NumberOfGCLogLevelOptions];
91+
GCLogging::Level typeGCLogLevelDefaultOptions[NumberOfGCLogLevelOptions];
92+
93+
int32_t typeInt32Options[NumberOfInt32Options];
94+
int32_t typeInt32DefaultOptions[NumberOfInt32Options];
95+
96+
unsigned typeUnsignedOptions[NumberOfUnsignedOptions];
97+
unsigned typeUnsignedDefaultOptions[NumberOfUnsignedOptions];
98+
99+
double typeDoubleOptions[NumberOfDoubleOptions];
100+
double typeDoubleDefaultOptions[NumberOfDoubleOptions];
101+
102+
size_t typeSizeOptions[NumberOfSizeOptions];
103+
size_t typeSizeDefaultOptions[NumberOfSizeOptions];
104+
105+
const char* typeOptionStringOptions[NumberOfOptionStringOptions];
106+
const char* typeOptionStringDefaultOptions[NumberOfOptionStringOptions];
107+
108+
OptionRange typeOptionRangeOptions[NumberOfOptionRangeOptions];
109+
OptionRange typeOptionRangeDefaultOptions[NumberOfOptionRangeOptions];
87110
};
88111
char ensureSize[ConfigSizeToProtect];
89112
};

‎Source/JavaScriptCore/runtime/OptionEntry.h‎

Lines changed: 0 additions & 84 deletions
This file was deleted.

0 commit comments

Comments
 (0)