1010#include < cstdlib>
1111#include < cstring>
1212#include < iomanip>
13+ #include < set>
1314#include < sstream>
1415
1516#include " src/base/functional.h"
@@ -103,7 +104,12 @@ struct Flag {
103104 const char * cmt_; // A comment about the flags purpose.
104105 bool owns_ptr_; // Does the flag own its string value?
105106 SetBy set_by_ = SetBy::kDefault ;
107+ // Name of the flag implying this flag, if any.
106108 const char * implied_by_ = nullptr ;
109+ #ifdef DEBUG
110+ // Pointer to the flag implying this flag, if any.
111+ const Flag* implied_by_ptr_ = nullptr ;
112+ #endif
107113
108114 FlagType type () const { return type_; }
109115
@@ -113,6 +119,17 @@ struct Flag {
113119
114120 bool PointsTo (const void * ptr) const { return valptr_ == ptr; }
115121
122+ #ifdef DEBUG
123+ bool ImpliedBy (const void * ptr) const {
124+ const Flag* current = this ->implied_by_ptr_ ;
125+ while (current != nullptr ) {
126+ if (current->PointsTo (ptr)) return true ;
127+ current = current->implied_by_ptr_ ;
128+ }
129+ return false ;
130+ }
131+ #endif
132+
116133 bool bool_variable () const { return GetValue<TYPE_BOOL, bool >(); }
117134
118135 void set_bool_variable (bool value, SetBy set_by) {
@@ -333,6 +350,15 @@ struct Flag {
333350 if (IsAnyImplication (new_set_by)) {
334351 DCHECK_NOT_NULL (implied_by);
335352 implied_by_ = implied_by;
353+ #ifdef DEBUG
354+ // This only works when implied_by is a flag_name or !flag_name, but it
355+ // can also be a condition e.g. flag_name > 3. Since this is only used for
356+ // checks in DEBUG mode, we will just ignore the more complex conditions
357+ // for now - that will just lead to a nullptr which won't be followed.
358+ implied_by_ptr_ = static_cast <Flag*>(
359+ FindFlagByName (implied_by[0 ] == ' !' ? implied_by + 1 : implied_by));
360+ DCHECK_NE (implied_by_ptr_, this );
361+ #endif
336362 }
337363 return change_flag;
338364 }
@@ -534,17 +560,70 @@ uint32_t ComputeFlagListHash() {
534560 std::ostringstream modified_args_as_string;
535561 if (COMPRESS_POINTERS_BOOL) modified_args_as_string << " ptr-compr" ;
536562 if (DEBUG_BOOL) modified_args_as_string << " debug" ;
563+
564+ #ifdef DEBUG
565+ // These two sets are used to check that we don't leave out any flags
566+ // implied by --predictable in the list below.
567+ std::set<const char *> flags_implied_by_predictable;
568+ std::set<const char *> flags_ignored_because_of_predictable;
569+ #endif
570+
537571 for (const Flag& flag : flags) {
538572 if (flag.IsDefault ()) continue ;
573+ #ifdef DEBUG
574+ if (flag.ImpliedBy (&v8_flags.predictable )) {
575+ flags_implied_by_predictable.insert (flag.name ());
576+ }
577+ #endif
539578 // We want to be able to flip --profile-deserialization without
540579 // causing the code cache to get invalidated by this hash.
541580 if (flag.PointsTo (&v8_flags.profile_deserialization )) continue ;
542581 // Skip v8_flags.random_seed and v8_flags.predictable to allow predictable
543582 // code caching.
544583 if (flag.PointsTo (&v8_flags.random_seed )) continue ;
545584 if (flag.PointsTo (&v8_flags.predictable )) continue ;
585+
586+ // The following flags are implied by --predictable (some negated).
587+ if (flag.PointsTo (&v8_flags.concurrent_sparkplug ) ||
588+ flag.PointsTo (&v8_flags.concurrent_recompilation ) ||
589+ #ifdef V8_ENABLE_MAGLEV
590+ flag.PointsTo (&v8_flags.maglev_deopt_data_on_background ) ||
591+ flag.PointsTo (&v8_flags.maglev_build_code_on_background ) ||
592+ #endif
593+ flag.PointsTo (&v8_flags.parallel_scavenge ) ||
594+ flag.PointsTo (&v8_flags.concurrent_marking ) ||
595+ flag.PointsTo (&v8_flags.concurrent_array_buffer_sweeping ) ||
596+ flag.PointsTo (&v8_flags.parallel_marking ) ||
597+ flag.PointsTo (&v8_flags.concurrent_sweeping ) ||
598+ flag.PointsTo (&v8_flags.parallel_compaction ) ||
599+ flag.PointsTo (&v8_flags.parallel_pointer_update ) ||
600+ flag.PointsTo (&v8_flags.memory_reducer ) ||
601+ flag.PointsTo (&v8_flags.cppheap_concurrent_marking ) ||
602+ flag.PointsTo (&v8_flags.cppheap_incremental_marking ) ||
603+ flag.PointsTo (&v8_flags.single_threaded_gc )) {
604+ #ifdef DEBUG
605+ if (flag.ImpliedBy (&v8_flags.predictable )) {
606+ flags_ignored_because_of_predictable.insert (flag.name ());
607+ }
608+ #endif
609+ continue ;
610+ }
546611 modified_args_as_string << flag;
547612 }
613+
614+ #ifdef DEBUG
615+ for (const char * name : flags_implied_by_predictable) {
616+ if (flags_ignored_because_of_predictable.find (name) ==
617+ flags_ignored_because_of_predictable.end ()) {
618+ PrintF (
619+ " %s should be added to the list of "
620+ " flags_ignored_because_of_predictable\n " ,
621+ name);
622+ UNREACHABLE ();
623+ }
624+ }
625+ #endif
626+
548627 std::string args (modified_args_as_string.str ());
549628 // Generate a hash that is not 0.
550629 uint32_t hash = static_cast <uint32_t >(base::hash_range (
0 commit comments