• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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