1 // Copyright 2019 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 // This file defines the hints classed gathered temporarily by the 6 // SerializerForBackgroundCompilation while it's analysing the bytecode 7 // and copying the necessary data to the JSHeapBroker for further usage 8 // by the reducers that run on the background thread. 9 10 #ifndef V8_COMPILER_SERIALIZER_HINTS_H_ 11 #define V8_COMPILER_SERIALIZER_HINTS_H_ 12 13 #include "src/compiler/functional-list.h" 14 #include "src/handles/handles.h" 15 #include "src/zone/zone-containers.h" 16 17 namespace v8 { 18 namespace internal { 19 20 class Context; 21 class Object; 22 class Map; 23 24 namespace compiler { 25 26 template <typename T, typename EqualTo> 27 class FunctionalSet { 28 public: Add(T const & elem,Zone * zone)29 void Add(T const& elem, Zone* zone) { 30 for (auto const& l : data_) { 31 if (equal_to(l, elem)) return; 32 } 33 data_.PushFront(elem, zone); 34 } 35 Union(FunctionalSet<T,EqualTo> other,Zone * zone)36 void Union(FunctionalSet<T, EqualTo> other, Zone* zone) { 37 if (!data_.TriviallyEquals(other.data_)) { 38 // Choose the larger side as tail. 39 if (data_.Size() < other.data_.Size()) std::swap(data_, other.data_); 40 for (auto const& elem : other.data_) Add(elem, zone); 41 } 42 } 43 IsEmpty()44 bool IsEmpty() const { return data_.begin() == data_.end(); } 45 46 // Warning: quadratic time complexity. Includes(FunctionalSet<T,EqualTo> const & other)47 bool Includes(FunctionalSet<T, EqualTo> const& other) const { 48 return std::all_of(other.begin(), other.end(), [&](T const& other_elem) { 49 return std::any_of(this->begin(), this->end(), [&](T const& this_elem) { 50 return equal_to(this_elem, other_elem); 51 }); 52 }); 53 } 54 bool operator==(const FunctionalSet<T, EqualTo>& other) const { 55 return this->data_.TriviallyEquals(other.data_) || 56 (this->data_.Size() == other.data_.Size() && this->Includes(other) && 57 other.Includes(*this)); 58 } 59 bool operator!=(const FunctionalSet<T, EqualTo>& other) const { 60 return !(*this == other); 61 } 62 Size()63 size_t Size() const { return data_.Size(); } 64 65 using iterator = typename FunctionalList<T>::iterator; 66 begin()67 iterator begin() const { return data_.begin(); } end()68 iterator end() const { return data_.end(); } 69 70 private: 71 static EqualTo equal_to; 72 FunctionalList<T> data_; 73 }; 74 75 template <typename T, typename EqualTo> 76 EqualTo FunctionalSet<T, EqualTo>::equal_to; 77 78 struct VirtualContext { 79 unsigned int distance; 80 Handle<Context> context; 81 VirtualContextVirtualContext82 VirtualContext(unsigned int distance_in, Handle<Context> context_in) 83 : distance(distance_in), context(context_in) { 84 CHECK_GT(distance, 0); 85 } 86 bool operator==(const VirtualContext& other) const { 87 return context.equals(other.context) && distance == other.distance; 88 } 89 }; 90 91 class VirtualClosure; 92 struct VirtualBoundFunction; 93 94 using ConstantsSet = FunctionalSet<Handle<Object>, Handle<Object>::equal_to>; 95 using VirtualContextsSet = 96 FunctionalSet<VirtualContext, std::equal_to<VirtualContext>>; 97 using MapsSet = FunctionalSet<Handle<Map>, Handle<Map>::equal_to>; 98 using VirtualClosuresSet = 99 FunctionalSet<VirtualClosure, std::equal_to<VirtualClosure>>; 100 using VirtualBoundFunctionsSet = 101 FunctionalSet<VirtualBoundFunction, std::equal_to<VirtualBoundFunction>>; 102 103 struct HintsImpl; 104 class JSHeapBroker; 105 106 class Hints { 107 public: 108 Hints() = default; // Empty. 109 static Hints SingleConstant(Handle<Object> constant, Zone* zone); 110 static Hints SingleMap(Handle<Map> map, Zone* zone); 111 112 // For inspection only. 113 ConstantsSet constants() const; 114 MapsSet maps() const; 115 VirtualClosuresSet virtual_closures() const; 116 VirtualContextsSet virtual_contexts() const; 117 VirtualBoundFunctionsSet virtual_bound_functions() const; 118 119 bool IsEmpty() const; 120 bool operator==(Hints const& other) const; 121 bool operator!=(Hints const& other) const; 122 123 #ifdef ENABLE_SLOW_DCHECKS 124 bool Includes(Hints const& other) const; 125 #endif 126 127 Hints Copy(Zone* zone) const; // Shallow. 128 Hints CopyToParentZone(Zone* zone, JSHeapBroker* broker) const; // Deep. 129 130 // As an optimization, empty hints can be represented as {impl_} being 131 // {nullptr}, i.e., as not having allocated a {HintsImpl} object. As a 132 // consequence, some operations need to force allocation prior to doing their 133 // job. In particular, backpropagation from a child serialization 134 // can only work if the hints were already allocated in the parent zone. IsAllocated()135 bool IsAllocated() const { return impl_ != nullptr; } EnsureShareable(Zone * zone)136 void EnsureShareable(Zone* zone) { EnsureAllocated(zone, false); } 137 138 // Make {this} an alias of {other}. 139 void Reset(Hints* other, Zone* zone); 140 141 void Merge(Hints const& other, Zone* zone, JSHeapBroker* broker); 142 143 // Destructive updates: if the hints are shared by several registers, 144 // then the following updates will be seen by all of them: 145 void AddConstant(Handle<Object> constant, Zone* zone, JSHeapBroker* broker); 146 void AddMap(Handle<Map> map, Zone* zone, JSHeapBroker* broker, 147 bool check_zone_equality = true); 148 void AddVirtualClosure(VirtualClosure const& virtual_closure, Zone* zone, 149 JSHeapBroker* broker); 150 void AddVirtualContext(VirtualContext const& virtual_context, Zone* zone, 151 JSHeapBroker* broker); 152 void AddVirtualBoundFunction(VirtualBoundFunction const& bound_function, 153 Zone* zone, JSHeapBroker* broker); 154 void Add(Hints const& other, Zone* zone, JSHeapBroker* broker); 155 156 private: 157 friend std::ostream& operator<<(std::ostream&, const Hints& hints); 158 HintsImpl* impl_ = nullptr; 159 160 void EnsureAllocated(Zone* zone, bool check_zone_equality = true); 161 162 // Helper for Add and Merge. 163 bool Union(Hints const& other); 164 165 static const size_t kMaxHintsSize = 50; 166 static_assert(kMaxHintsSize >= 1, "must allow for at least one hint"); 167 }; 168 169 using HintsVector = ZoneVector<Hints>; 170 171 } // namespace compiler 172 } // namespace internal 173 } // namespace v8 174 175 #endif // V8_COMPILER_SERIALIZER_HINTS_H_ 176