• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/flags.h"
6 
7 #include <cctype>
8 #include <cerrno>
9 #include <cstdlib>
10 #include <sstream>
11 
12 #include "src/allocation.h"
13 #include "src/assembler.h"
14 #include "src/base/functional.h"
15 #include "src/base/platform/platform.h"
16 #include "src/ostreams.h"
17 #include "src/utils.h"
18 #include "src/wasm/wasm-limits.h"
19 
20 namespace v8 {
21 namespace internal {
22 
23 // Define all of our flags.
24 #define FLAG_MODE_DEFINE
25 #include "src/flag-definitions.h"  // NOLINT(build/include)
26 
27 // Define all of our flags default values.
28 #define FLAG_MODE_DEFINE_DEFAULTS
29 #include "src/flag-definitions.h"  // NOLINT(build/include)
30 
31 namespace {
32 
33 // This structure represents a single entry in the flag system, with a pointer
34 // to the actual flag, default value, comment, etc.  This is designed to be POD
35 // initialized as to avoid requiring static constructors.
36 struct Flag {
37   enum FlagType {
38     TYPE_BOOL,
39     TYPE_MAYBE_BOOL,
40     TYPE_INT,
41     TYPE_UINT,
42     TYPE_UINT64,
43     TYPE_FLOAT,
44     TYPE_SIZE_T,
45     TYPE_STRING,
46     TYPE_ARGS
47   };
48 
49   FlagType type_;           // What type of flag, bool, int, or string.
50   const char* name_;        // Name of the flag, ex "my_flag".
51   void* valptr_;            // Pointer to the global flag variable.
52   const void* defptr_;      // Pointer to the default value.
53   const char* cmt_;         // A comment about the flags purpose.
54   bool owns_ptr_;           // Does the flag own its string value?
55 
typev8::internal::__anon6d4d84af0111::Flag56   FlagType type() const { return type_; }
57 
namev8::internal::__anon6d4d84af0111::Flag58   const char* name() const { return name_; }
59 
commentv8::internal::__anon6d4d84af0111::Flag60   const char* comment() const { return cmt_; }
61 
bool_variablev8::internal::__anon6d4d84af0111::Flag62   bool* bool_variable() const {
63     DCHECK(type_ == TYPE_BOOL);
64     return reinterpret_cast<bool*>(valptr_);
65   }
66 
maybe_bool_variablev8::internal::__anon6d4d84af0111::Flag67   MaybeBoolFlag* maybe_bool_variable() const {
68     DCHECK(type_ == TYPE_MAYBE_BOOL);
69     return reinterpret_cast<MaybeBoolFlag*>(valptr_);
70   }
71 
int_variablev8::internal::__anon6d4d84af0111::Flag72   int* int_variable() const {
73     DCHECK(type_ == TYPE_INT);
74     return reinterpret_cast<int*>(valptr_);
75   }
76 
uint_variablev8::internal::__anon6d4d84af0111::Flag77   unsigned int* uint_variable() const {
78     DCHECK(type_ == TYPE_UINT);
79     return reinterpret_cast<unsigned int*>(valptr_);
80   }
81 
uint64_variablev8::internal::__anon6d4d84af0111::Flag82   uint64_t* uint64_variable() const {
83     DCHECK(type_ == TYPE_UINT64);
84     return reinterpret_cast<uint64_t*>(valptr_);
85   }
86 
float_variablev8::internal::__anon6d4d84af0111::Flag87   double* float_variable() const {
88     DCHECK(type_ == TYPE_FLOAT);
89     return reinterpret_cast<double*>(valptr_);
90   }
91 
size_t_variablev8::internal::__anon6d4d84af0111::Flag92   size_t* size_t_variable() const {
93     DCHECK(type_ == TYPE_SIZE_T);
94     return reinterpret_cast<size_t*>(valptr_);
95   }
96 
string_valuev8::internal::__anon6d4d84af0111::Flag97   const char* string_value() const {
98     DCHECK(type_ == TYPE_STRING);
99     return *reinterpret_cast<const char**>(valptr_);
100   }
101 
set_string_valuev8::internal::__anon6d4d84af0111::Flag102   void set_string_value(const char* value, bool owns_ptr) {
103     DCHECK(type_ == TYPE_STRING);
104     const char** ptr = reinterpret_cast<const char**>(valptr_);
105     if (owns_ptr_ && *ptr != nullptr) DeleteArray(*ptr);
106     *ptr = value;
107     owns_ptr_ = owns_ptr;
108   }
109 
args_variablev8::internal::__anon6d4d84af0111::Flag110   JSArguments* args_variable() const {
111     DCHECK(type_ == TYPE_ARGS);
112     return reinterpret_cast<JSArguments*>(valptr_);
113   }
114 
bool_defaultv8::internal::__anon6d4d84af0111::Flag115   bool bool_default() const {
116     DCHECK(type_ == TYPE_BOOL);
117     return *reinterpret_cast<const bool*>(defptr_);
118   }
119 
int_defaultv8::internal::__anon6d4d84af0111::Flag120   int int_default() const {
121     DCHECK(type_ == TYPE_INT);
122     return *reinterpret_cast<const int*>(defptr_);
123   }
124 
uint_defaultv8::internal::__anon6d4d84af0111::Flag125   unsigned int uint_default() const {
126     DCHECK(type_ == TYPE_UINT);
127     return *reinterpret_cast<const unsigned int*>(defptr_);
128   }
129 
uint64_defaultv8::internal::__anon6d4d84af0111::Flag130   uint64_t uint64_default() const {
131     DCHECK(type_ == TYPE_UINT64);
132     return *reinterpret_cast<const uint64_t*>(defptr_);
133   }
134 
float_defaultv8::internal::__anon6d4d84af0111::Flag135   double float_default() const {
136     DCHECK(type_ == TYPE_FLOAT);
137     return *reinterpret_cast<const double*>(defptr_);
138   }
139 
size_t_defaultv8::internal::__anon6d4d84af0111::Flag140   size_t size_t_default() const {
141     DCHECK(type_ == TYPE_SIZE_T);
142     return *reinterpret_cast<const size_t*>(defptr_);
143   }
144 
string_defaultv8::internal::__anon6d4d84af0111::Flag145   const char* string_default() const {
146     DCHECK(type_ == TYPE_STRING);
147     return *reinterpret_cast<const char* const *>(defptr_);
148   }
149 
args_defaultv8::internal::__anon6d4d84af0111::Flag150   JSArguments args_default() const {
151     DCHECK(type_ == TYPE_ARGS);
152     return *reinterpret_cast<const JSArguments*>(defptr_);
153   }
154 
155   // Compare this flag's current value against the default.
IsDefaultv8::internal::__anon6d4d84af0111::Flag156   bool IsDefault() const {
157     switch (type_) {
158       case TYPE_BOOL:
159         return *bool_variable() == bool_default();
160       case TYPE_MAYBE_BOOL:
161         return maybe_bool_variable()->has_value == false;
162       case TYPE_INT:
163         return *int_variable() == int_default();
164       case TYPE_UINT:
165         return *uint_variable() == uint_default();
166       case TYPE_UINT64:
167         return *uint64_variable() == uint64_default();
168       case TYPE_FLOAT:
169         return *float_variable() == float_default();
170       case TYPE_SIZE_T:
171         return *size_t_variable() == size_t_default();
172       case TYPE_STRING: {
173         const char* str1 = string_value();
174         const char* str2 = string_default();
175         if (str2 == nullptr) return str1 == nullptr;
176         if (str1 == nullptr) return str2 == nullptr;
177         return strcmp(str1, str2) == 0;
178       }
179       case TYPE_ARGS:
180         return args_variable()->argc == 0;
181     }
182     UNREACHABLE();
183   }
184 
185   // Set a flag back to it's default value.
Resetv8::internal::__anon6d4d84af0111::Flag186   void Reset() {
187     switch (type_) {
188       case TYPE_BOOL:
189         *bool_variable() = bool_default();
190         break;
191       case TYPE_MAYBE_BOOL:
192         *maybe_bool_variable() = MaybeBoolFlag::Create(false, false);
193         break;
194       case TYPE_INT:
195         *int_variable() = int_default();
196         break;
197       case TYPE_UINT:
198         *uint_variable() = uint_default();
199         break;
200       case TYPE_UINT64:
201         *uint64_variable() = uint64_default();
202         break;
203       case TYPE_FLOAT:
204         *float_variable() = float_default();
205         break;
206       case TYPE_SIZE_T:
207         *size_t_variable() = size_t_default();
208         break;
209       case TYPE_STRING:
210         set_string_value(string_default(), false);
211         break;
212       case TYPE_ARGS:
213         *args_variable() = args_default();
214         break;
215     }
216   }
217 };
218 
219 Flag flags[] = {
220 #define FLAG_MODE_META
221 #include "src/flag-definitions.h"  // NOLINT(build/include)
222 };
223 
224 const size_t num_flags = sizeof(flags) / sizeof(*flags);
225 
226 }  // namespace
227 
228 
Type2String(Flag::FlagType type)229 static const char* Type2String(Flag::FlagType type) {
230   switch (type) {
231     case Flag::TYPE_BOOL: return "bool";
232     case Flag::TYPE_MAYBE_BOOL: return "maybe_bool";
233     case Flag::TYPE_INT: return "int";
234     case Flag::TYPE_UINT:
235       return "uint";
236     case Flag::TYPE_UINT64:
237       return "uint64";
238     case Flag::TYPE_FLOAT: return "float";
239     case Flag::TYPE_SIZE_T:
240       return "size_t";
241     case Flag::TYPE_STRING: return "string";
242     case Flag::TYPE_ARGS: return "arguments";
243   }
244   UNREACHABLE();
245 }
246 
247 
operator <<(std::ostream & os,const Flag & flag)248 std::ostream& operator<<(std::ostream& os, const Flag& flag) {  // NOLINT
249   switch (flag.type()) {
250     case Flag::TYPE_BOOL:
251       os << (*flag.bool_variable() ? "true" : "false");
252       break;
253     case Flag::TYPE_MAYBE_BOOL:
254       os << (flag.maybe_bool_variable()->has_value
255                  ? (flag.maybe_bool_variable()->value ? "true" : "false")
256                  : "unset");
257       break;
258     case Flag::TYPE_INT:
259       os << *flag.int_variable();
260       break;
261     case Flag::TYPE_UINT:
262       os << *flag.uint_variable();
263       break;
264     case Flag::TYPE_UINT64:
265       os << *flag.uint64_variable();
266       break;
267     case Flag::TYPE_FLOAT:
268       os << *flag.float_variable();
269       break;
270     case Flag::TYPE_SIZE_T:
271       os << *flag.size_t_variable();
272       break;
273     case Flag::TYPE_STRING: {
274       const char* str = flag.string_value();
275       os << (str ? str : "nullptr");
276       break;
277     }
278     case Flag::TYPE_ARGS: {
279       JSArguments args = *flag.args_variable();
280       if (args.argc > 0) {
281         os << args[0];
282         for (int i = 1; i < args.argc; i++) {
283           os << args[i];
284         }
285       }
286       break;
287     }
288   }
289   return os;
290 }
291 
292 
293 // static
argv()294 std::vector<const char*>* FlagList::argv() {
295   std::vector<const char*>* args = new std::vector<const char*>(8);
296   Flag* args_flag = nullptr;
297   for (size_t i = 0; i < num_flags; ++i) {
298     Flag* f = &flags[i];
299     if (!f->IsDefault()) {
300       if (f->type() == Flag::TYPE_ARGS) {
301         DCHECK_NULL(args_flag);
302         args_flag = f;  // Must be last in arguments.
303         continue;
304       }
305       {
306         bool disabled = f->type() == Flag::TYPE_BOOL && !*f->bool_variable();
307         std::ostringstream os;
308         os << (disabled ? "--no" : "--") << f->name();
309         args->push_back(StrDup(os.str().c_str()));
310       }
311       if (f->type() != Flag::TYPE_BOOL) {
312         std::ostringstream os;
313         os << *f;
314         args->push_back(StrDup(os.str().c_str()));
315       }
316     }
317   }
318   if (args_flag != nullptr) {
319     std::ostringstream os;
320     os << "--" << args_flag->name();
321     args->push_back(StrDup(os.str().c_str()));
322     JSArguments jsargs = *args_flag->args_variable();
323     for (int j = 0; j < jsargs.argc; j++) {
324       args->push_back(StrDup(jsargs[j]));
325     }
326   }
327   return args;
328 }
329 
330 
NormalizeChar(char ch)331 inline char NormalizeChar(char ch) {
332   return ch == '_' ? '-' : ch;
333 }
334 
335 // Helper function to parse flags: Takes an argument arg and splits it into
336 // a flag name and flag value (or nullptr if they are missing). negated is set
337 // if the arg started with "-no" or "--no". The buffer may be used to NUL-
338 // terminate the name, it must be large enough to hold any possible name.
SplitArgument(const char * arg,char * buffer,int buffer_size,const char ** name,const char ** value,bool * negated)339 static void SplitArgument(const char* arg, char* buffer, int buffer_size,
340                           const char** name, const char** value,
341                           bool* negated) {
342   *name = nullptr;
343   *value = nullptr;
344   *negated = false;
345 
346   if (arg != nullptr && *arg == '-') {
347     // find the begin of the flag name
348     arg++;  // remove 1st '-'
349     if (*arg == '-') {
350       arg++;  // remove 2nd '-'
351       if (arg[0] == '\0') {
352         const char* kJSArgumentsFlagName = "js_arguments";
353         *name = kJSArgumentsFlagName;
354         return;
355       }
356     }
357     if (arg[0] == 'n' && arg[1] == 'o') {
358       arg += 2;  // remove "no"
359       if (NormalizeChar(arg[0]) == '-') arg++;  // remove dash after "no".
360       *negated = true;
361     }
362     *name = arg;
363 
364     // find the end of the flag name
365     while (*arg != '\0' && *arg != '=')
366       arg++;
367 
368     // get the value if any
369     if (*arg == '=') {
370       // make a copy so we can NUL-terminate flag name
371       size_t n = arg - *name;
372       CHECK(n < static_cast<size_t>(buffer_size));  // buffer is too small
373       MemCopy(buffer, *name, n);
374       buffer[n] = '\0';
375       *name = buffer;
376       // get the value
377       *value = arg + 1;
378     }
379   }
380 }
381 
382 
EqualNames(const char * a,const char * b)383 static bool EqualNames(const char* a, const char* b) {
384   for (int i = 0; NormalizeChar(a[i]) == NormalizeChar(b[i]); i++) {
385     if (a[i] == '\0') {
386       return true;
387     }
388   }
389   return false;
390 }
391 
392 
FindFlag(const char * name)393 static Flag* FindFlag(const char* name) {
394   for (size_t i = 0; i < num_flags; ++i) {
395     if (EqualNames(name, flags[i].name()))
396       return &flags[i];
397   }
398   return nullptr;
399 }
400 
401 template <typename T>
TryParseUnsigned(Flag * flag,const char * arg,const char * value,char ** endp,T * out_val)402 bool TryParseUnsigned(Flag* flag, const char* arg, const char* value,
403                       char** endp, T* out_val) {
404   // We do not use strtoul because it accepts negative numbers.
405   // Rejects values >= 2**63 when T is 64 bits wide but that
406   // seems like an acceptable trade-off.
407   uint64_t max = static_cast<uint64_t>(std::numeric_limits<T>::max());
408   errno = 0;
409   int64_t val = static_cast<int64_t>(strtoll(value, endp, 10));
410   if (val < 0 || static_cast<uint64_t>(val) > max || errno != 0) {
411     PrintF(stderr,
412            "Error: Value for flag %s of type %s is out of bounds "
413            "[0-%" PRIu64 "]\n",
414            arg, Type2String(flag->type()), max);
415     return false;
416   }
417   *out_val = static_cast<T>(val);
418   return true;
419 }
420 
421 // static
SetFlagsFromCommandLine(int * argc,char ** argv,bool remove_flags)422 int FlagList::SetFlagsFromCommandLine(int* argc,
423                                       char** argv,
424                                       bool remove_flags) {
425   int return_code = 0;
426   // parse arguments
427   for (int i = 1; i < *argc;) {
428     int j = i;  // j > 0
429     const char* arg = argv[i++];
430 
431     // split arg into flag components
432     char buffer[1*KB];
433     const char* name;
434     const char* value;
435     bool negated;
436     SplitArgument(arg, buffer, sizeof buffer, &name, &value, &negated);
437 
438     if (name != nullptr) {
439       // lookup the flag
440       Flag* flag = FindFlag(name);
441       if (flag == nullptr) {
442         if (remove_flags) {
443           // We don't recognize this flag but since we're removing
444           // the flags we recognize we assume that the remaining flags
445           // will be processed somewhere else so this flag might make
446           // sense there.
447           continue;
448         } else {
449           PrintF(stderr, "Error: unrecognized flag %s\n", arg);
450           return_code = j;
451           break;
452         }
453       }
454 
455       // if we still need a flag value, use the next argument if available
456       if (flag->type() != Flag::TYPE_BOOL &&
457           flag->type() != Flag::TYPE_MAYBE_BOOL &&
458           flag->type() != Flag::TYPE_ARGS && value == nullptr) {
459         if (i < *argc) {
460           value = argv[i++];
461         }
462         if (!value) {
463           PrintF(stderr, "Error: missing value for flag %s of type %s\n", arg,
464                  Type2String(flag->type()));
465           return_code = j;
466           break;
467         }
468       }
469 
470       // set the flag
471       char* endp = const_cast<char*>("");  // *endp is only read
472       switch (flag->type()) {
473         case Flag::TYPE_BOOL:
474           *flag->bool_variable() = !negated;
475           break;
476         case Flag::TYPE_MAYBE_BOOL:
477           *flag->maybe_bool_variable() = MaybeBoolFlag::Create(true, !negated);
478           break;
479         case Flag::TYPE_INT:
480           *flag->int_variable() = static_cast<int>(strtol(value, &endp, 10));
481           break;
482         case Flag::TYPE_UINT:
483           if (!TryParseUnsigned(flag, arg, value, &endp,
484                                 flag->uint_variable())) {
485             return_code = j;
486           }
487           break;
488         case Flag::TYPE_UINT64:
489           if (!TryParseUnsigned(flag, arg, value, &endp,
490                                 flag->uint64_variable())) {
491             return_code = j;
492           }
493           break;
494         case Flag::TYPE_FLOAT:
495           *flag->float_variable() = strtod(value, &endp);
496           break;
497         case Flag::TYPE_SIZE_T:
498           if (!TryParseUnsigned(flag, arg, value, &endp,
499                                 flag->size_t_variable())) {
500             return_code = j;
501           }
502           break;
503         case Flag::TYPE_STRING:
504           flag->set_string_value(value ? StrDup(value) : nullptr, true);
505           break;
506         case Flag::TYPE_ARGS: {
507           int start_pos = (value == nullptr) ? i : i - 1;
508           int js_argc = *argc - start_pos;
509           const char** js_argv = NewArray<const char*>(js_argc);
510           if (value != nullptr) {
511             js_argv[0] = StrDup(value);
512           }
513           for (int k = i; k < *argc; k++) {
514             js_argv[k - start_pos] = StrDup(argv[k]);
515           }
516           *flag->args_variable() = JSArguments::Create(js_argc, js_argv);
517           i = *argc;  // Consume all arguments
518           break;
519         }
520       }
521 
522       // handle errors
523       bool is_bool_type = flag->type() == Flag::TYPE_BOOL ||
524           flag->type() == Flag::TYPE_MAYBE_BOOL;
525       if ((is_bool_type && value != nullptr) || (!is_bool_type && negated) ||
526           *endp != '\0') {
527         // TODO(neis): TryParseUnsigned may return with {*endp == '\0'} even in
528         // an error case.
529         PrintF(stderr, "Error: illegal value for flag %s of type %s\n", arg,
530                Type2String(flag->type()));
531         if (is_bool_type) {
532           PrintF(stderr,
533                  "To set or unset a boolean flag, use --flag or --no-flag.\n");
534         }
535         return_code = j;
536         break;
537       }
538 
539       // remove the flag & value from the command
540       if (remove_flags) {
541         while (j < i) {
542           argv[j++] = nullptr;
543         }
544       }
545     }
546   }
547 
548   if (FLAG_help) {
549     PrintHelp();
550     exit(0);
551   }
552 
553   if (remove_flags) {
554     // shrink the argument list
555     int j = 1;
556     for (int i = 1; i < *argc; i++) {
557       if (argv[i] != nullptr) argv[j++] = argv[i];
558     }
559     *argc = j;
560   } else if (return_code != 0) {
561     if (return_code + 1 < *argc) {
562       PrintF(stderr, "The remaining arguments were ignored:");
563       for (int i = return_code + 1; i < *argc; ++i) {
564         PrintF(stderr, " %s", argv[i]);
565       }
566       PrintF(stderr, "\n");
567     }
568   }
569   if (return_code != 0) PrintF(stderr, "Try --help for options\n");
570 
571   return return_code;
572 }
573 
574 
SkipWhiteSpace(char * p)575 static char* SkipWhiteSpace(char* p) {
576   while (*p != '\0' && isspace(*p) != 0) p++;
577   return p;
578 }
579 
580 
SkipBlackSpace(char * p)581 static char* SkipBlackSpace(char* p) {
582   while (*p != '\0' && isspace(*p) == 0) p++;
583   return p;
584 }
585 
586 
587 // static
SetFlagsFromString(const char * str,int len)588 int FlagList::SetFlagsFromString(const char* str, int len) {
589   // make a 0-terminated copy of str
590   ScopedVector<char> copy0(len + 1);
591   MemCopy(copy0.start(), str, len);
592   copy0[len] = '\0';
593 
594   // strip leading white space
595   char* copy = SkipWhiteSpace(copy0.start());
596 
597   // count the number of 'arguments'
598   int argc = 1;  // be compatible with SetFlagsFromCommandLine()
599   for (char* p = copy; *p != '\0'; argc++) {
600     p = SkipBlackSpace(p);
601     p = SkipWhiteSpace(p);
602   }
603 
604   // allocate argument array
605   ScopedVector<char*> argv(argc);
606 
607   // split the flags string into arguments
608   argc = 1;  // be compatible with SetFlagsFromCommandLine()
609   for (char* p = copy; *p != '\0'; argc++) {
610     argv[argc] = p;
611     p = SkipBlackSpace(p);
612     if (*p != '\0') *p++ = '\0';  // 0-terminate argument
613     p = SkipWhiteSpace(p);
614   }
615 
616   return SetFlagsFromCommandLine(&argc, argv.start(), false);
617 }
618 
619 
620 // static
ResetAllFlags()621 void FlagList::ResetAllFlags() {
622   for (size_t i = 0; i < num_flags; ++i) {
623     flags[i].Reset();
624   }
625 }
626 
627 
628 // static
PrintHelp()629 void FlagList::PrintHelp() {
630   CpuFeatures::Probe(false);
631   CpuFeatures::PrintTarget();
632   CpuFeatures::PrintFeatures();
633 
634   StdoutStream os;
635   os << "Synopsis:\n"
636         "  shell [options] [--shell] [<file>...]\n"
637         "  d8 [options] [-e <string>] [--shell] [[--module] <file>...]\n\n"
638         "  -e        execute a string in V8\n"
639         "  --shell   run an interactive JavaScript shell\n"
640         "  --module  execute a file as a JavaScript module\n\n"
641         "Note: the --module option is implicitly enabled for *.mjs files.\n\n"
642         "Options:\n";
643 
644   for (const Flag& f : flags) {
645     os << "  --";
646     for (const char* c = f.name(); *c != '\0'; ++c) {
647       os << NormalizeChar(*c);
648     }
649     os << " (" << f.comment() << ")\n"
650        << "        type: " << Type2String(f.type()) << "  default: " << f
651        << "\n";
652   }
653 }
654 
655 
656 static uint32_t flag_hash = 0;
657 
658 
ComputeFlagListHash()659 void ComputeFlagListHash() {
660   std::ostringstream modified_args_as_string;
661 #ifdef DEBUG
662   modified_args_as_string << "debug";
663 #endif  // DEBUG
664   if (FLAG_embedded_builtins) {
665     modified_args_as_string << "embedded";
666   }
667   for (size_t i = 0; i < num_flags; ++i) {
668     Flag* current = &flags[i];
669     if (!current->IsDefault()) {
670       modified_args_as_string << i;
671       modified_args_as_string << *current;
672     }
673   }
674   std::string args(modified_args_as_string.str());
675   flag_hash = static_cast<uint32_t>(
676       base::hash_range(args.c_str(), args.c_str() + args.length()));
677 }
678 
679 
680 // static
EnforceFlagImplications()681 void FlagList::EnforceFlagImplications() {
682 #define FLAG_MODE_DEFINE_IMPLICATIONS
683 #include "src/flag-definitions.h"  // NOLINT(build/include)
684 #undef FLAG_MODE_DEFINE_IMPLICATIONS
685   ComputeFlagListHash();
686 }
687 
688 
Hash()689 uint32_t FlagList::Hash() { return flag_hash; }
690 }  // namespace internal
691 }  // namespace v8
692