V8 Project
effects.h
Go to the documentation of this file.
1 // Copyright 2013 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 #ifndef V8_EFFECTS_H_
6 #define V8_EFFECTS_H_
7 
8 #include "src/v8.h"
9 
10 #include "src/types.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 
16 // A simple struct to represent (write) effects. A write is represented as a
17 // modification of type bounds (e.g. of a variable).
18 //
19 // An effect can either be definite, if the write is known to have taken place,
20 // or 'possible', if it was optional. The difference is relevant when composing
21 // effects.
22 //
23 // There are two ways to compose effects: sequentially (they happen one after
24 // the other) or alternatively (either one or the other happens). A definite
25 // effect cancels out any previous effect upon sequencing. A possible effect
26 // merges into a previous effect, i.e., type bounds are merged. Alternative
27 // composition always merges bounds. It yields a possible effect if at least
28 // one was only possible.
29 struct Effect {
31 
34 
36  explicit Effect(Bounds b, Modality m = DEFINITE) : modality(m), bounds(b) {}
37 
38  // The unknown effect.
39  static Effect Unknown(Zone* zone) {
40  return Effect(Bounds::Unbounded(zone), POSSIBLE);
41  }
42 
43  static Effect Forget(Zone* zone) {
44  return Effect(Bounds::Unbounded(zone), DEFINITE);
45  }
46 
47  // Sequential composition, as in 'e1; e2'.
48  static Effect Seq(Effect e1, Effect e2, Zone* zone) {
49  if (e2.modality == DEFINITE) return e2;
50  return Effect(Bounds::Either(e1.bounds, e2.bounds, zone), e1.modality);
51  }
52 
53  // Alternative composition, as in 'cond ? e1 : e2'.
54  static Effect Alt(Effect e1, Effect e2, Zone* zone) {
55  return Effect(
56  Bounds::Either(e1.bounds, e2.bounds, zone),
57  e1.modality == POSSIBLE ? POSSIBLE : e2.modality);
58  }
59 };
60 
61 
62 // Classes encapsulating sets of effects on variables.
63 //
64 // Effects maps variables to effects and supports sequential and alternative
65 // composition.
66 //
67 // NestedEffects is an incremental representation that supports persistence
68 // through functional extension. It represents the map as an adjoin of a list
69 // of maps, whose tail can be shared.
70 //
71 // Both classes provide similar interfaces, implemented in parts through the
72 // EffectsMixin below (using sandwich style, to work around the style guide's
73 // MI restriction).
74 //
75 // We also (ab)use Effects/NestedEffects as a representation for abstract
76 // store typings. In that case, only definite effects are of interest.
77 
78 template<class Var, class Base, class Effects>
79 class EffectsMixin: public Base {
80  public:
81  explicit EffectsMixin(Zone* zone) : Base(zone) {}
82 
83  Effect Lookup(Var var) {
84  Locator locator;
85  return this->Find(var, &locator)
86  ? locator.value() : Effect::Unknown(Base::zone());
87  }
88 
89  Bounds LookupBounds(Var var) {
90  Effect effect = Lookup(var);
91  return effect.modality == Effect::DEFINITE
92  ? effect.bounds : Bounds::Unbounded(Base::zone());
93  }
94 
95  // Sequential composition.
96  void Seq(Var var, Effect effect) {
97  Locator locator;
98  if (!this->Insert(var, &locator)) {
99  effect = Effect::Seq(locator.value(), effect, Base::zone());
100  }
101  locator.set_value(effect);
102  }
103 
104  void Seq(Effects that) {
105  SeqMerger<EffectsMixin> merge = { *this };
106  that.ForEach(&merge);
107  }
108 
109  // Alternative composition.
110  void Alt(Var var, Effect effect) {
111  Locator locator;
112  if (!this->Insert(var, &locator)) {
113  effect = Effect::Alt(locator.value(), effect, Base::zone());
114  }
115  locator.set_value(effect);
116  }
117 
118  void Alt(Effects that) {
119  AltWeakener<EffectsMixin> weaken = { *this, that };
120  this->ForEach(&weaken);
121  AltMerger<EffectsMixin> merge = { *this };
122  that.ForEach(&merge);
123  }
124 
125  // Invalidation.
126  void Forget() {
127  Overrider override = {
128  Effect::Forget(Base::zone()), Effects(Base::zone()) };
129  this->ForEach(&override);
130  Seq(override.effects);
131  }
132 
133  protected:
134  typedef typename Base::Locator Locator;
135 
136  template<class Self>
137  struct SeqMerger {
138  void Call(Var var, Effect effect) { self.Seq(var, effect); }
139  Self self;
140  };
141 
142  template<class Self>
143  struct AltMerger {
144  void Call(Var var, Effect effect) { self.Alt(var, effect); }
145  Self self;
146  };
147 
148  template<class Self>
149  struct AltWeakener {
150  void Call(Var var, Effect effect) {
151  if (effect.modality == Effect::DEFINITE && !other.Contains(var)) {
152  effect.modality = Effect::POSSIBLE;
153  Locator locator;
154  self.Insert(var, &locator);
155  locator.set_value(effect);
156  }
157  }
158  Self self;
160  };
161 
162  struct Overrider {
163  void Call(Var var, Effect effect) { effects.Seq(var, new_effect); }
166  };
167 };
168 
169 
170 template<class Var, Var kNoVar> class Effects;
171 template<class Var, Var kNoVar> class NestedEffectsBase;
172 
173 template<class Var, Var kNoVar>
174 class EffectsBase {
175  public:
176  explicit EffectsBase(Zone* zone) : map_(new(zone) Mapping(zone)) {}
177 
178  bool IsEmpty() { return map_->is_empty(); }
179 
180  protected:
181  friend class NestedEffectsBase<Var, kNoVar>;
182  friend class
184 
185  Zone* zone() { return map_->allocator().zone(); }
186 
188  typedef Var Key;
189  typedef Effect Value;
190  static const Var kNoKey = kNoVar;
191  static Effect NoValue() { return Effect(); }
192  static int Compare(int x, int y) { return y - x; }
193  };
195  typedef typename Mapping::Locator Locator;
196 
197  bool Contains(Var var) {
198  DCHECK(var != kNoVar);
199  return map_->Contains(var);
200  }
201  bool Find(Var var, Locator* locator) {
202  DCHECK(var != kNoVar);
203  return map_->Find(var, locator);
204  }
205  bool Insert(Var var, Locator* locator) {
206  DCHECK(var != kNoVar);
207  return map_->Insert(var, locator);
208  }
209 
210  template<class Callback>
211  void ForEach(Callback* callback) {
212  return map_->ForEach(callback);
213  }
214 
215  private:
216  Mapping* map_;
217 };
218 
219 template<class Var, Var kNoVar>
221 
222 template<class Var, Var kNoVar>
223 class Effects: public
224  EffectsMixin<Var, EffectsBase<Var, kNoVar>, Effects<Var, kNoVar> > {
225  public:
226  explicit Effects(Zone* zone)
227  : EffectsMixin<Var, EffectsBase<Var, kNoVar>, Effects<Var, kNoVar> >(zone)
228  {}
229 };
230 
231 
232 template<class Var, Var kNoVar>
234  public:
235  explicit NestedEffectsBase(Zone* zone) : node_(new(zone) Node(zone)) {}
236 
237  template<class Callback>
238  void ForEach(Callback* callback) {
239  if (node_->previous) NestedEffectsBase(node_->previous).ForEach(callback);
240  node_->effects.ForEach(callback);
241  }
242 
244 
245  bool IsEmpty() {
246  for (Node* node = node_; node != NULL; node = node->previous) {
247  if (!node->effects.IsEmpty()) return false;
248  }
249  return true;
250  }
251 
252  protected:
254 
255  Zone* zone() { return node_->zone; }
256 
257  void push() { node_ = new(node_->zone) Node(node_->zone, node_); }
258  void pop() { node_ = node_->previous; }
259  bool is_empty() { return node_ == NULL; }
260 
261  bool Contains(Var var) {
262  DCHECK(var != kNoVar);
263  for (Node* node = node_; node != NULL; node = node->previous) {
264  if (node->effects.Contains(var)) return true;
265  }
266  return false;
267  }
268 
269  bool Find(Var var, Locator* locator) {
270  DCHECK(var != kNoVar);
271  for (Node* node = node_; node != NULL; node = node->previous) {
272  if (node->effects.Find(var, locator)) return true;
273  }
274  return false;
275  }
276 
277  bool Insert(Var var, Locator* locator);
278 
279  private:
280  struct Node: ZoneObject {
284  explicit Node(Zone* zone, Node* previous = NULL)
286  };
287 
288  explicit NestedEffectsBase(Node* node) : node_(node) {}
289 
291 };
292 
293 
294 template<class Var, Var kNoVar>
296  DCHECK(var != kNoVar);
297  if (!node_->effects.Insert(var, locator)) return false;
298  Locator shadowed;
299  for (Node* node = node_->previous; node != NULL; node = node->previous) {
300  if (node->effects.Find(var, &shadowed)) {
301  // Initialize with shadowed entry.
302  locator->set_value(shadowed.value());
303  return false;
304  }
305  }
306  return true;
307 }
308 
309 
310 template<class Var, Var kNoVar>
311 class NestedEffects: public
312  EffectsMixin<Var, NestedEffectsBase<Var, kNoVar>, Effects<Var, kNoVar> > {
313  public:
314  explicit NestedEffects(Zone* zone) :
315  EffectsMixin<Var, NestedEffectsBase<Var, kNoVar>, Effects<Var, kNoVar> >(
316  zone) {}
317 
318  // Create an extension of the current effect set. The current set should not
319  // be modified while the extension is in use.
321  NestedEffects result = *this;
322  result.push();
323  return result;
324  }
325 
327  NestedEffects result = *this;
328  result.pop();
329  DCHECK(!this->is_empty());
330  return result;
331  }
332 };
333 
334 } } // namespace v8::internal
335 
336 #endif // V8_EFFECTS_H_
bool Contains(Var var)
Definition: effects.h:196
bool Find(Var var, Locator *locator)
Definition: effects.h:200
bool Insert(Var var, Locator *locator)
Definition: effects.h:204
Mapping::Locator Locator
Definition: effects.h:194
ZoneSplayTree< SplayTreeConfig > Mapping
Definition: effects.h:193
EffectsBase(Zone *zone)
Definition: effects.h:176
void ForEach(Callback *callback)
Definition: effects.h:210
void Seq(Var var, Effect effect)
Definition: effects.h:96
void Seq(Effects that)
Definition: effects.h:104
void Alt(Effects that)
Definition: effects.h:118
Effect Lookup(Var var)
Definition: effects.h:83
void Alt(Var var, Effect effect)
Definition: effects.h:110
EffectsMixin(Zone *zone)
Definition: effects.h:81
Bounds LookupBounds(Var var)
Definition: effects.h:89
Base::Locator Locator
Definition: effects.h:134
Effects(Zone *zone)
Definition: effects.h:226
Effects< Var, kNoVar > Top()
Definition: effects.h:243
bool Find(Var var, Locator *locator)
Definition: effects.h:269
bool Insert(Var var, Locator *locator)
Definition: effects.h:295
void ForEach(Callback *callback)
Definition: effects.h:238
EffectsBase< Var, kNoVar >::Locator Locator
Definition: effects.h:253
NestedEffects Pop()
Definition: effects.h:326
NestedEffects(Zone *zone)
Definition: effects.h:314
NestedEffects Push()
Definition: effects.h:320
AllocationPolicy allocator()
Definition: splay-tree.h:54
bool Contains(const Key &key)
void ForEach(Callback *callback)
bool Find(const Key &key, Locator *locator)
bool Insert(const Key &key, Locator *locator)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
Definition: logging.h:205
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
static BoundsImpl Unbounded(Region *region)
Definition: types.h:1010
static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region *region)
Definition: types.h:1024
static Effect Unknown(Zone *zone)
Definition: effects.h:39
Modality modality
Definition: effects.h:32
Effect(Bounds b, Modality m=DEFINITE)
Definition: effects.h:36
static Effect Alt(Effect e1, Effect e2, Zone *zone)
Definition: effects.h:54
static Effect Forget(Zone *zone)
Definition: effects.h:43
static Effect Seq(Effect e1, Effect e2, Zone *zone)
Definition: effects.h:48
static int Compare(int x, int y)
Definition: effects.h:191
void Call(Var var, Effect effect)
Definition: effects.h:144
void Call(Var var, Effect effect)
Definition: effects.h:150
void Call(Var var, Effect effect)
Definition: effects.h:163
void Call(Var var, Effect effect)
Definition: effects.h:138
Node(Zone *zone, Node *previous=NULL)
Definition: effects.h:284
Effects< Var, kNoVar > effects
Definition: effects.h:282