31#if V8_ENABLE_WEBASSEMBLY
49#define FLAG_MODE_DEFINE_DEFAULTS
51#undef FLAG_MODE_DEFINE_DEFAULTS
61 if (ac < bc)
return -1;
62 if (ac > bc)
return 1;
78 for (
int i = 0;
true; ++
i) {
81 if (ac ==
'\0')
break;
82 if (ac != bc)
return false;
84 return bc ==
'\0' || std::isspace(bc);
87std::ostream&
operator<<(std::ostream& os, FlagName flag_name) {
88 os << (flag_name.negated ?
"--no-" :
"--");
89 for (
const char* p = flag_name.name; *p; ++p) {
102 ? !new_value || std::strcmp(old_value, new_value) != 0
108 *
reinterpret_cast<FlagValue<const char*>*
>(
valptr_) = new_value;
116 if (
v8_flags.allow_overwriting_for_next_flag) {
119 v8_flags.allow_overwriting_for_next_flag =
false;
127 const char* implied_by) {
133 static constexpr const char kHint[] =
134 "If a test variant caused this, it might be necessary to specify "
135 "additional contradictory flags in "
136 "tools/testrunner/local/variants.py.";
137 struct FatalError :
public std::ostringstream {
140 ~FatalError() {
FATAL(
"%s.\n%s", str().c_str(), kHint); }
146 if (implied_by ==
nullptr) {
147 FatalError{} <<
"Contradictory value for readonly flag "
151 FatalError{} <<
"Contradictory value for readonly flag "
152 << FlagName{
name()} <<
" implied by " << implied_by;
169 FatalError{} <<
"Contradictory weak flag implications from "
171 << FlagName{implied_by} <<
" for flag "
177 FatalError{} <<
"Contradictory flag implications from "
179 << FlagName{implied_by} <<
" for flag "
188 FatalError{} <<
"Flag " << FlagName{
name()} <<
": value implied by "
189 << FlagName{implied_by}
190 <<
" conflicts with explicit specification";
192 FatalError{} <<
"Flag " << FlagName{
name()} <<
" is implied by "
193 << FlagName{implied_by}
194 <<
" but also specified explicitly";
200 FatalError{} <<
"Command-line provided flag " << FlagName{
name()}
201 <<
" specified as both true and false";
203 FatalError{} <<
"Command-line provided flag " << FlagName{
name()}
204 <<
" specified multiple times";
224 implied_by[0] ==
'!' ? implied_by + 1 : implied_by));
250 if (str2 ==
nullptr)
return str1 ==
nullptr;
251 if (str1 ==
nullptr)
return str2 ==
nullptr;
252 return strcmp(str1, str2) == 0;
293#define FLAG_MODE_META
330 auto it = std::lower_bound(
flags_.rbegin(),
flags_.rend(), name,
332 if (it ==
flags_.rend())
return nullptr;
345 Flag* flag = GetFlagMap()->GetFlag(name);
346 CHECK(flag !=
nullptr);
354 Flag* flag = GetFlagMap()->GetFlag(name);
371 if (flags[
i].PointsTo(ptr))
return &flags[
i];
404 switch (flag.type()) {
406 os << (flag.bool_variable() ?
"true" :
"false");
409 os << (flag.maybe_bool_variable().has_value()
410 ? (flag.maybe_bool_variable().value() ?
"true" :
"false")
414 os << flag.int_variable();
417 os << flag.uint_variable();
420 os << flag.uint64_variable();
423 os << flag.float_variable();
426 os << flag.size_t_variable();
429 const char* str = flag.string_value();
430 os << std::quoted(str ? str :
"");
439 os <<
FlagName{flag.name(), !flag.bool_variable()};
450 std::ostringstream modified_args_as_string;
452 if (
DEBUG_BOOL) modified_args_as_string <<
"debug";
457 std::set<const char*> flags_implied_by_predictable;
458 std::set<const char*> flags_ignored_because_of_predictable;
461 for (
const Flag& flag : flags) {
462 if (flag.IsDefault())
continue;
464 if (flag.ImpliedBy(&
v8_flags.predictable)) {
465 flags_implied_by_predictable.insert(flag.name());
470 if (flag.PointsTo(&
v8_flags.profile_deserialization))
continue;
473 if (flag.PointsTo(&
v8_flags.random_seed))
continue;
474 if (flag.PointsTo(&
v8_flags.predictable))
continue;
477 if (flag.PointsTo(&
v8_flags.concurrent_sparkplug) ||
478 flag.PointsTo(&
v8_flags.concurrent_recompilation) ||
479 flag.PointsTo(&
v8_flags.lazy_feedback_allocation) ||
480#ifdef V8_ENABLE_MAGLEV
481 flag.PointsTo(&
v8_flags.maglev_deopt_data_on_background) ||
482 flag.PointsTo(&
v8_flags.maglev_build_code_on_background) ||
484 flag.PointsTo(&
v8_flags.parallel_scavenge) ||
485 flag.PointsTo(&
v8_flags.concurrent_marking) ||
486 flag.PointsTo(&
v8_flags.concurrent_minor_ms_marking) ||
487 flag.PointsTo(&
v8_flags.concurrent_array_buffer_sweeping) ||
488 flag.PointsTo(&
v8_flags.parallel_marking) ||
489 flag.PointsTo(&
v8_flags.concurrent_sweeping) ||
490 flag.PointsTo(&
v8_flags.parallel_compaction) ||
491 flag.PointsTo(&
v8_flags.parallel_pointer_update) ||
492 flag.PointsTo(&
v8_flags.parallel_weak_ref_clearing) ||
493 flag.PointsTo(&
v8_flags.memory_reducer) ||
494 flag.PointsTo(&
v8_flags.cppheap_concurrent_marking) ||
495 flag.PointsTo(&
v8_flags.cppheap_incremental_marking) ||
496 flag.PointsTo(&
v8_flags.single_threaded_gc) ||
497 flag.PointsTo(&
v8_flags.fuzzing_and_concurrent_recompilation) ||
498 flag.PointsTo(&
v8_flags.predictable_and_random_seed_is_0)) {
500 if (flag.ImpliedBy(&
v8_flags.predictable)) {
501 flags_ignored_because_of_predictable.insert(flag.name());
506 modified_args_as_string << flag;
515 for (
const char* name : flags_implied_by_predictable) {
516 if (flags_ignored_because_of_predictable.find(name) ==
517 flags_ignored_because_of_predictable.end()) {
519 "%s should be added to the list of "
520 "flags_ignored_because_of_predictable\n",
528 std::string
args(modified_args_as_string.str());
542 const char** name,
const char** value,
548 if (arg[0] !=
'-')
return;
556 if (arg[0] ==
'n' && arg[1] ==
'o') {
566 while (*arg !=
'\0' && *arg !=
'=') arg++;
571 size_t n = arg - *
name;
572 CHECK(n <
static_cast<size_t>(buffer_size));
582 char** endp, T* out_val) {
586 uint64_t max =
static_cast<uint64_t
>(std::numeric_limits<T>::max());
588 int64_t val =
static_cast<int64_t
>(strtoll(value, endp, 10));
589 if (val < 0 ||
static_cast<uint64_t
>(val) > max || errno != 0) {
591 "Error: Value for flag %s of type %s is out of bounds "
596 *out_val =
static_cast<T
>(val);
614 for (
int i = 1;
i < *argc;) {
616 const char* arg = argv[
i++];
617 if (arg ==
nullptr)
continue;
620 if (arg[0] ==
'-' && arg[1] ==
'-' && arg[2] ==
'\0')
break;
627 SplitArgument(arg, buffer,
sizeof buffer, &name, &value, &negated);
629 if (name ==
nullptr)
continue;
633 if (flag ==
nullptr) {
641 PrintF(stderr,
"Error: unrecognized flag %s\n", arg);
654 PrintF(stderr,
"Error: missing value for flag %s of type %s\n", arg,
662 char* endp =
const_cast<char*
>(
"");
663 switch (flag->type()) {
671 flag->set_int_variable(
static_cast<int>(strtol(value, &endp, 10)),
675 unsigned int parsed_value;
684 uint64_t parsed_value;
693 flag->set_float_variable(strtod(value, &endp),
706 flag->set_string_value(value ?
StrDup(value) :
nullptr,
true,
714 if ((is_bool_type && value !=
nullptr) || (!is_bool_type && negated) ||
718 PrintF(stderr,
"Error: illegal value for flag %s of type %s\n", arg,
722 "To set or unset a boolean flag, use --flag or --no-flag.\n");
746 if (
v8_flags.print_feature_flags_json) {
756 for (
int i = 1;
i < *argc;
i++) {
757 if (argv[
i] !=
nullptr) argv[j++] = argv[
i];
760 }
else if (return_code != 0) {
761 if (return_code + 1 < *argc) {
762 PrintF(stderr,
"The remaining arguments were ignored:");
763 for (
int i = return_code + 1;
i < *argc; ++
i) {
764 PrintF(stderr,
" %s", argv[
i]);
769 if (return_code != 0)
PrintF(stderr,
"Try --help for options\n");
775 while (*p !=
'\0' && isspace(*p) != 0) p++;
780 while (*p !=
'\0' && isspace(*p) == 0) p++;
788 MemCopy(copy0.get(), str, len);
796 for (
char* p = copy; *p !=
'\0'; argc++) {
806 for (
char* p = copy; *p !=
'\0'; argc++) {
809 if (*p !=
'\0') *p++ =
'\0';
837 flags[
i].ReleaseDynamicAllocations();
848 os <<
"The following syntax for options is accepted (both '-' and '--' are "
850 " --flag (bool flags only)\n"
851 " --no-flag (bool flags only)\n"
852 " --flag=value (non-bool flags only, no spaces around '=')\n"
853 " --flag value (non-bool flags only)\n"
854 " -- (captures all remaining args in JavaScript)\n\n";
857 for (
const Flag& f : flags) {
858 os <<
" " <<
FlagName{f.name()} <<
" (" << f.comment() <<
")\n"
859 <<
" type: " <<
Type2String(f.type()) <<
" default: " << f
867 for (
const Flag& f : flags) {
874void PrintFlagsJSONArray(std::ostream& os,
875 const std::vector<const char*>& flags) {
881 for (
const auto& flag : flags) {
882 if (!first) os <<
",\n";
883 os <<
" \"" << flag <<
"\"";
890void PrintFeatureFlagsJSONObject(
891 std::ostream& os,
const std::vector<const char*>& inprogress_flags,
892 const std::vector<const char*>& staged_flags,
893 const std::vector<const char*>& shipping_flags) {
896 os <<
" \"in-progress\": ";
897 PrintFlagsJSONArray(os, inprogress_flags);
900 os <<
" \"staged\": ";
901 PrintFlagsJSONArray(os, staged_flags);
904 os <<
" \"shipping\": ";
905 PrintFlagsJSONArray(os, shipping_flags);
920 std::vector<const char*> inprogress_flags;
921 std::vector<const char*> staged_flags;
922 std::vector<const char*> shipping_flags;
924#define ADD_JS_INPROGRESS_FLAG(name, desc) inprogress_flags.push_back(#name);
925#define ADD_JS_STAGED_FLAG(name, desc) staged_flags.push_back(#name);
926#define ADD_JS_SHIPPING_FLAG(name, desc) shipping_flags.push_back(#name);
933 PrintFeatureFlagsJSONObject(os, inprogress_flags, staged_flags,
939 std::vector<const char*> inprogress_flags;
940 std::vector<const char*> staged_flags;
941 std::vector<const char*> shipping_flags;
947 os <<
" \"harmony\": ";
948 PrintFeatureFlagsJSONObject(os, inprogress_flags, staged_flags,
953#if V8_ENABLE_WEBASSEMBLY
955 std::vector<const char*> inprogress_flags;
956 std::vector<const char*> staged_flags;
957 std::vector<const char*> shipping_flags;
959#define ADD_WASM_INPROGRESS_FLAG(name, desc, val) \
960 inprogress_flags.push_back("experimental_wasm_" #name);
961#define ADD_WASM_STAGED_FLAG(name, desc, val) \
962 staged_flags.push_back("experimental_wasm_" #name);
963#define ADD_WASM_SHIPPED_FLAG(name, desc, val) \
964 shipping_flags.push_back("experimental_wasm_" #name);
971 PrintFeatureFlagsJSONObject(os, inprogress_flags, staged_flags,
979#undef ADD_JS_INPROGRESS_FLAG
980#undef ADD_JS_STAGED_FLAG
981#undef ADD_JS_SHIPPING_FLAG
982#undef ADD_WASM_INPROGRESS_FLAG
983#undef ADD_WASM_STAGED_FLAG
984#undef ADD_WASM_SHIPPED_FLAG
989class ImplicationProcessor {
992 bool EnforceImplications() {
993 bool changed =
false;
994#define FLAG_MODE_DEFINE_IMPLICATIONS
996#undef FLAG_MODE_DEFINE_IMPLICATIONS
1004 bool TriggerImplication(
bool premise,
const char* premise_name,
1005 FlagValue<T>* conclusion_value,
1006 const char* conclusion_name, T value,
1007 bool weak_implication) {
1008 if (!premise)
return false;
1010 if (!conclusion_flag->CheckFlagChange(
1013 conclusion_value->value() != value, premise_name)) {
1016 if (
V8_UNLIKELY(num_iterations_ >= kMaxNumIterations)) {
1017 cycle_ <<
"\n" << FlagName{premise_name} <<
" -> ";
1018 if constexpr (std::is_same_v<T, bool>) {
1019 cycle_ << FlagName{conclusion_flag->name(), !value};
1021 cycle_ << FlagName{conclusion_flag->name()} <<
" = " <<
value;
1024 *conclusion_value =
value;
1032 bool TriggerImplication(
bool premise,
const char* premise_name,
1033 const FlagValue<T>* conclusion_value,
1034 const char* conclusion_name, T value,
1035 bool weak_implication) {
1036 if (!premise)
return false;
1039 DCHECK(conclusion_flag->IsReadOnly());
1040 if (!conclusion_flag->CheckFlagChange(
1043 conclusion_value->value() != value, premise_name)) {
1048 DCHECK_EQ(value, conclusion_flag->GetDefaultValue<T>());
1052 void CheckForCycle() {
1055 if (++num_iterations_ < kMaxNumIterations)
return;
1057 if (num_iterations_ == kMaxNumIterations) {
1070 FATAL(
"Cycle in flag implications:%s",
cycle_.str().c_str());
1073 DCHECK_GE(2 * kMaxNumIterations, num_iterations_);
1089#define CONTRADICTION(flag1, flag2) \
1090 (v8_flags.flag1 || v8_flags.flag2) \
1091 ? std::make_tuple(FindFlagByPointer(&v8_flags.flag1), \
1092 FindFlagByPointer(&v8_flags.flag2)) \
1093 : std::make_tuple(nullptr, nullptr)
1095#define RESET_WHEN_FUZZING(flag) CONTRADICTION(flag, fuzzing)
1096#define RESET_WHEN_CORRECTNESS_FUZZING(flag) \
1097 CONTRADICTION(flag, correctness_fuzzer_suppressions)
1103 std::tuple<Flag*, Flag*> contradictions[] = {
1107 CONTRADICTION(always_osr_from_maglev, disable_optimizing_compilers),
1112 CONTRADICTION(always_turbofan, disable_optimizing_compilers),
1117 CONTRADICTION(assert_types, stress_concurrent_inlining_attach_code),
1119 CONTRADICTION(disable_optimizing_compilers, stress_concurrent_inlining),
1121 stress_concurrent_inlining_attach_code),
1124 turboshaft_wasm_in_js_inlining),
1127 CONTRADICTION(jitless, stress_concurrent_inlining_attach_code),
1132 CONTRADICTION(lite_mode, stress_concurrent_inlining_attach_code),
1135 CONTRADICTION(predictable, stress_concurrent_inlining_attach_code),
1137 CONTRADICTION(single_threaded, stress_concurrent_inlining_attach_code),
1138 CONTRADICTION(stress_concurrent_inlining, turboshaft_assert_types),
1140 turboshaft_assert_types),
1142 CONTRADICTION(turboshaft, stress_concurrent_inlining_attach_code),
1165 for (
auto [flag1, flag2] : contradictions) {
1166 if (!flag1 || !flag2)
continue;
1167 if (flag1->IsDefault() || flag2->IsDefault())
continue;
1171 CHECK(!flag1->PointsTo(&
v8_flags.correctness_fuzzer_suppressions));
1173 std::cerr <<
"Warning: resetting flag --" << flag1->name()
1174 <<
" due to conflicting flags" << std::endl;
1178 v8_flags.fuzzing_and_concurrent_recompilation) {
1180 <<
"Use --nofuzzing-and-concurrent-recompilation to force "
1181 "enable --trace-turbo, and friends. This is not thread-safe.\n";
1189 for (ImplicationProcessor proc; proc.EnforceImplications();) {
1197 if (uint32_t hash =
flag_hash.load(std::memory_order_relaxed))
return hash;
1199 flag_hash.store(hash, std::memory_order_relaxed);
constexpr int kMinimumOSPageSize
static void ExitProcess(int exit_code)
static void SetDataReadOnly(void *address, size_t size)
constexpr T * begin() const
static void Probe(bool cross_compile)
static void PrintFeatures()
static void PrintTarget()
static bool EqualNames(const char *a, const char *b)
static char NormalizeChar(char ch)
static int FlagNamesCmp(const char *a, const char *b)
static bool EqualNameWithSuffix(const char *a, const char *b)
static int SetFlagsFromString(const char *str, size_t len)
static void EnforceFlagImplications()
static void PrintValues()
static int SetFlagsFromCommandLine(int *argc, char **argv, bool remove_flags, FlagList::HelpOptions help_options=FlagList::HelpOptions())
static void ReleaseDynamicAllocations()
static void PrintFeatureFlagsJSON()
static void ResolveContradictionsWhenFuzzing()
static void ResetFlagHash()
static void FreezeFlags()
Flag * GetFlag(const char *name)
std::array< Flag *, kNumFlags > flags_
#define COMPRESS_POINTERS_BOOL
base::Vector< const DirectHandle< Object > > args
#define JAVASCRIPT_INPROGRESS_FEATURES(V)
#define HARMONY_SHIPPING(V)
#define JAVASCRIPT_STAGED_FEATURES(V)
#define HARMONY_INPROGRESS(V)
#define JAVASCRIPT_SHIPPING_FEATURES(V)
#define HARMONY_STAGED(V)
static constexpr size_t kMaxNumIterations
#define ADD_JS_STAGED_FLAG(name, desc)
std::ostringstream cycle_
#define RESET_WHEN_FUZZING(flag)
#define CONTRADICTION(flag1, flag2)
#define ADD_JS_INPROGRESS_FLAG(name, desc)
#define ADD_JS_SHIPPING_FLAG(name, desc)
uint32_t cycle_start_hash_
#define RESET_WHEN_CORRECTNESS_FUZZING(flag)
#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName,...)
V8_INLINE size_t hash_range(Iterator first, Iterator last)
constexpr Vector< T > ArrayVector(T(&arr)[N])
void DeleteArray(T *array)
V8_EXPORT_PRIVATE base::Vector< Flag > Flags()
V8_EXPORT_PRIVATE Flag * FindFlagByName(const char *name)
constexpr size_t kNumFlags
void PrintF(const char *format,...)
Flag * FindFlagByPointer(const void *ptr)
static void SplitArgument(const char *arg, char *buffer, int buffer_size, const char **name, const char **value, bool *negated)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
static char * SkipWhiteSpace(char *p)
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
static std::atomic< uint32_t > flag_hash
char * StrDup(const char *str)
static char * SkipBlackSpace(char *p)
bool TryParseUnsigned(Flag *flag, const char *arg, const char *value, char **endp, T *out_val)
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation trace turbo cfg trace TurboFan s graph trimmer trace TurboFan s control equivalence trace TurboFan s register allocator trace stack load store counters for optimized code in run fuzzing &&concurrent_recompilation trace_turbo trace_turbo_scheduled trace_turbo_stack_accesses verify TurboFan machine graph of code stubs enable FixedArray bounds checks print TurboFan statistics of wasm compilations maximum cumulative size of bytecode considered for inlining scale factor of bytecode size used to calculate the inlining budget * KB
static const char * Type2String(Flag::FlagType type)
V8_EXPORT_PRIVATE FlagValues v8_flags
V8_EXPORT_PRIVATE Flag * FindImplicationFlagByName(const char *name)
static std::atomic< bool > flags_frozen
FlagValues v8_flags PERMISSION_MUTABLE_SECTION
void MemCopy(void *dest, const void *src, size_t size)
uint32_t ComputeFlagListHash()
T * NewArray(size_t size)
#define MSVC_SUPPRESS_WARNING(n)
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
bool operator()(const Flag *a, const Flag *b) const
bool operator()(const Flag *a, const char *b) const
void set_bool_variable(bool value, SetBy set_by)
uint64_t uint64_default() const
double float_variable() const
std::optional< bool > maybe_bool_variable() const
double float_default() const
V8_EXPORT_PRIVATE void Reset()
const char * string_value() const
const char * name() const
size_t size_t_default() const
void set_uint64_variable(uint64_t value, SetBy set_by)
void set_size_t_variable(size_t value, SetBy set_by)
bool bool_variable() const
bool bool_default() const
void set_float_variable(double value, SetBy set_by)
unsigned int uint_variable() const
size_t size_t_variable() const
constexpr bool IsAnyImplication(Flag::SetBy set_by)
void set_maybe_bool_variable(std::optional< bool > value, SetBy set_by)
void set_uint_variable(unsigned int value, SetBy set_by)
void ReleaseDynamicAllocations()
void set_string_value(const char *new_value, bool owns_new_value, SetBy set_by)
unsigned int uint_default() const
bool CheckFlagChange(SetBy new_set_by, bool change_flag, const char *implied_by=nullptr)
void set_int_variable(int value, SetBy set_by)
static bool ShouldCheckFlagContradictions()
uint64_t uint64_variable() const
const char * string_default() const
#define V8_UNLIKELY(condition)
#define FOREACH_WASM_STAGING_FEATURE_FLAG(V)
#define FOREACH_WASM_SHIPPED_FEATURE_FLAG(V)
#define FOREACH_WASM_EXPERIMENTAL_FEATURE_FLAG(V)