v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
effects.h
Go to the documentation of this file.
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_EFFECTS_H_
29 #define V8_EFFECTS_H_
30 
31 #include "v8.h"
32 
33 #include "types.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 
39 // A simple struct to represent (write) effects. A write is represented as a
40 // modification of type bounds (e.g. of a variable).
41 //
42 // An effect can either be definite, if the write is known to have taken place,
43 // or 'possible', if it was optional. The difference is relevant when composing
44 // effects.
45 //
46 // There are two ways to compose effects: sequentially (they happen one after
47 // the other) or alternatively (either one or the other happens). A definite
48 // effect cancels out any previous effect upon sequencing. A possible effect
49 // merges into a previous effect, i.e., type bounds are merged. Alternative
50 // composition always merges bounds. It yields a possible effect if at least
51 // one was only possible.
52 struct Effect {
54 
57 
60 
61  // The unknown effect.
62  static Effect Unknown(Zone* zone) {
63  return Effect(Bounds::Unbounded(zone), POSSIBLE);
64  }
65 
66  static Effect Forget(Zone* zone) {
67  return Effect(Bounds::Unbounded(zone), DEFINITE);
68  }
69 
70  // Sequential composition, as in 'e1; e2'.
71  static Effect Seq(Effect e1, Effect e2, Zone* zone) {
72  if (e2.modality == DEFINITE) return e2;
73  return Effect(Bounds::Either(e1.bounds, e2.bounds, zone), e1.modality);
74  }
75 
76  // Alternative composition, as in 'cond ? e1 : e2'.
77  static Effect Alt(Effect e1, Effect e2, Zone* zone) {
78  return Effect(
79  Bounds::Either(e1.bounds, e2.bounds, zone),
80  e1.modality == POSSIBLE ? POSSIBLE : e2.modality);
81  }
82 };
83 
84 
85 // Classes encapsulating sets of effects on variables.
86 //
87 // Effects maps variables to effects and supports sequential and alternative
88 // composition.
89 //
90 // NestedEffects is an incremental representation that supports persistence
91 // through functional extension. It represents the map as an adjoin of a list
92 // of maps, whose tail can be shared.
93 //
94 // Both classes provide similar interfaces, implemented in parts through the
95 // EffectsMixin below (using sandwich style, to work around the style guide's
96 // MI restriction).
97 //
98 // We also (ab)use Effects/NestedEffects as a representation for abstract
99 // store typings. In that case, only definite effects are of interest.
100 
101 template<class Var, class Base, class Effects>
102 class EffectsMixin: public Base {
103  public:
104  explicit EffectsMixin(Zone* zone) : Base(zone) {}
105 
106  Effect Lookup(Var var) {
107  Locator locator;
108  return this->Find(var, &locator)
109  ? locator.value() : Effect::Unknown(Base::zone());
110  }
111 
112  Bounds LookupBounds(Var var) {
113  Effect effect = Lookup(var);
114  return effect.modality == Effect::DEFINITE
115  ? effect.bounds : Bounds::Unbounded(Base::zone());
116  }
117 
118  // Sequential composition.
119  void Seq(Var var, Effect effect) {
120  Locator locator;
121  if (!this->Insert(var, &locator)) {
122  effect = Effect::Seq(locator.value(), effect, Base::zone());
123  }
124  locator.set_value(effect);
125  }
126 
127  void Seq(Effects that) {
128  SeqMerger<EffectsMixin> merge = { *this };
129  that.ForEach(&merge);
130  }
131 
132  // Alternative composition.
133  void Alt(Var var, Effect effect) {
134  Locator locator;
135  if (!this->Insert(var, &locator)) {
136  effect = Effect::Alt(locator.value(), effect, Base::zone());
137  }
138  locator.set_value(effect);
139  }
140 
141  void Alt(Effects that) {
142  AltWeakener<EffectsMixin> weaken = { *this, that };
143  this->ForEach(&weaken);
144  AltMerger<EffectsMixin> merge = { *this };
145  that.ForEach(&merge);
146  }
147 
148  // Invalidation.
149  void Forget() {
150  Overrider override = {
151  Effect::Forget(Base::zone()), Effects(Base::zone()) };
152  this->ForEach(&override);
153  Seq(override.effects);
154  }
155 
156  protected:
157  typedef typename Base::Locator Locator;
158 
159  template<class Self>
160  struct SeqMerger {
161  void Call(Var var, Effect effect) { self.Seq(var, effect); }
162  Self self;
163  };
164 
165  template<class Self>
166  struct AltMerger {
167  void Call(Var var, Effect effect) { self.Alt(var, effect); }
168  Self self;
169  };
170 
171  template<class Self>
172  struct AltWeakener {
173  void Call(Var var, Effect effect) {
174  if (effect.modality == Effect::DEFINITE && !other.Contains(var)) {
175  effect.modality = Effect::POSSIBLE;
176  Locator locator;
177  self.Insert(var, &locator);
178  locator.set_value(effect);
179  }
180  }
181  Self self;
183  };
184 
185  struct Overrider {
186  void Call(Var var, Effect effect) { effects.Seq(var, new_effect); }
189  };
190 };
191 
192 
193 template<class Var, Var kNoVar> class Effects;
194 template<class Var, Var kNoVar> class NestedEffectsBase;
195 
196 template<class Var, Var kNoVar>
197 class EffectsBase {
198  public:
199  explicit EffectsBase(Zone* zone) : map_(new(zone) Mapping(zone)) {}
200 
201  bool IsEmpty() { return map_->is_empty(); }
202 
203  protected:
204  friend class NestedEffectsBase<Var, kNoVar>;
205  friend class
208  Zone* zone() { return map_->allocator().zone(); }
211  typedef Var Key;
212  typedef Effect Value;
213  static const Var kNoKey = kNoVar;
214  static Effect NoValue() { return Effect(); }
215  static int Compare(int x, int y) { return y - x; }
216  };
218  typedef typename Mapping::Locator Locator;
220  bool Contains(Var var) {
221  ASSERT(var != kNoVar);
222  return map_->Contains(var);
223  }
224  bool Find(Var var, Locator* locator) {
225  ASSERT(var != kNoVar);
226  return map_->Find(var, locator);
227  }
228  bool Insert(Var var, Locator* locator) {
229  ASSERT(var != kNoVar);
230  return map_->Insert(var, locator);
231  }
232 
233  template<class Callback>
234  void ForEach(Callback* callback) {
235  return map_->ForEach(callback);
236  }
237 
238  private:
239  Mapping* map_;
240 };
241 
242 template<class Var, Var kNoVar>
244 
245 template<class Var, Var kNoVar>
246 class Effects: public
247  EffectsMixin<Var, EffectsBase<Var, kNoVar>, Effects<Var, kNoVar> > {
248  public:
249  explicit Effects(Zone* zone)
250  : EffectsMixin<Var, EffectsBase<Var, kNoVar>, Effects<Var, kNoVar> >(zone)
251  {}
252 };
253 
254 
255 template<class Var, Var kNoVar>
256 class NestedEffectsBase {
257  public:
258  explicit NestedEffectsBase(Zone* zone) : node_(new(zone) Node(zone)) {}
259 
260  template<class Callback>
261  void ForEach(Callback* callback) {
262  if (node_->previous) NestedEffectsBase(node_->previous).ForEach(callback);
263  node_->effects.ForEach(callback);
264  }
265 
266  Effects<Var, kNoVar> Top() { return node_->effects; }
267 
268  bool IsEmpty() {
269  for (Node* node = node_; node != NULL; node = node->previous) {
270  if (!node->effects.IsEmpty()) return false;
271  }
272  return true;
273  }
274 
275  protected:
277 
278  Zone* zone() { return node_->zone; }
279 
280  void push() { node_ = new(node_->zone) Node(node_->zone, node_); }
281  void pop() { node_ = node_->previous; }
282  bool is_empty() { return node_ == NULL; }
283 
284  bool Contains(Var var) {
285  ASSERT(var != kNoVar);
286  for (Node* node = node_; node != NULL; node = node->previous) {
287  if (node->effects.Contains(var)) return true;
288  }
289  return false;
290  }
291 
292  bool Find(Var var, Locator* locator) {
293  ASSERT(var != kNoVar);
294  for (Node* node = node_; node != NULL; node = node->previous) {
295  if (node->effects.Find(var, locator)) return true;
296  }
297  return false;
298  }
299 
300  bool Insert(Var var, Locator* locator);
301 
302  private:
303  struct Node: ZoneObject {
304  Zone* zone;
305  Effects<Var, kNoVar> effects;
306  Node* previous;
307  explicit Node(Zone* zone, Node* previous = NULL)
308  : zone(zone), effects(zone), previous(previous) {}
309  };
310 
311  explicit NestedEffectsBase(Node* node) : node_(node) {}
312 
313  Node* node_;
314 };
315 
316 
317 template<class Var, Var kNoVar>
319  ASSERT(var != kNoVar);
320  if (!node_->effects.Insert(var, locator)) return false;
321  Locator shadowed;
322  for (Node* node = node_->previous; node != NULL; node = node->previous) {
323  if (node->effects.Find(var, &shadowed)) {
324  // Initialize with shadowed entry.
325  locator->set_value(shadowed.value());
326  return false;
327  }
328  }
329  return true;
330 }
331 
332 
333 template<class Var, Var kNoVar>
334 class NestedEffects: public
335  EffectsMixin<Var, NestedEffectsBase<Var, kNoVar>, Effects<Var, kNoVar> > {
336  public:
337  explicit NestedEffects(Zone* zone) :
338  EffectsMixin<Var, NestedEffectsBase<Var, kNoVar>, Effects<Var, kNoVar> >(
339  zone) {}
340 
341  // Create an extension of the current effect set. The current set should not
342  // be modified while the extension is in use.
344  NestedEffects result = *this;
345  result.push();
346  return result;
347  }
348 
350  NestedEffects result = *this;
351  result.pop();
352  ASSERT(!this->is_empty());
353  return result;
354  }
355 };
356 
357 } } // namespace v8::internal
358 
359 #endif // V8_EFFECTS_H_
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
void Call(Var var, Effect effect)
Definition: effects.h:161
Bounds LookupBounds(Var var)
Definition: effects.h:112
Effects(Zone *zone)
Definition: effects.h:249
bool Find(const Key &key, Locator *locator)
bool Insert(const Key &key, Locator *locator)
void ForEach(Callback *callback)
Definition: effects.h:261
Effect Lookup(Var var)
Definition: effects.h:106
NestedEffects(Zone *zone)
Definition: effects.h:337
Modality modality
Definition: effects.h:55
bool Contains(const Key &key)
void ForEach(Callback *callback)
EffectsBase(Zone *zone)
Definition: effects.h:199
Effect(Bounds b, Modality m=DEFINITE)
Definition: effects.h:59
void Alt(Var var, Effect effect)
Definition: effects.h:133
#define ASSERT(condition)
Definition: checks.h:329
void Seq(Effects that)
Definition: effects.h:127
Base::Locator Locator
Definition: effects.h:157
Mapping::Locator Locator
Definition: effects.h:217
EffectsBase< Var, kNoVar >::Locator Locator
Definition: effects.h:276
void Alt(Effects that)
Definition: effects.h:141
NestedEffects Push()
Definition: effects.h:343
bool Find(Var var, Locator *locator)
Definition: effects.h:292
bool Contains(Var var)
Definition: effects.h:219
void Call(Var var, Effect effect)
Definition: effects.h:167
NestedEffects Pop()
Definition: effects.h:349
static int Compare(int x, int y)
Definition: effects.h:214
bool Insert(Var var, Locator *locator)
Definition: effects.h:227
EffectsMixin(Zone *zone)
Definition: effects.h:104
static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region *region)
Definition: types.h:621
void Call(Var var, Effect effect)
Definition: effects.h:186
void Seq(Var var, Effect effect)
Definition: effects.h:119
AllocationPolicy allocator()
Definition: splay-tree.h:77
static Effect Seq(Effect e1, Effect e2, Zone *zone)
Definition: effects.h:71
void Call(Var var, Effect effect)
Definition: effects.h:173
Effects< Var, kNoVar > Top()
Definition: effects.h:266
bool Find(Var var, Locator *locator)
Definition: effects.h:223
static BoundsImpl Unbounded(Region *region)
Definition: types.h:607
static Effect Unknown(Zone *zone)
Definition: effects.h:62
ZoneSplayTree< SplayTreeConfig > Mapping
Definition: effects.h:216
void ForEach(Callback *callback)
Definition: effects.h:233
static Effect Alt(Effect e1, Effect e2, Zone *zone)
Definition: effects.h:77
static Effect Forget(Zone *zone)
Definition: effects.h:66
bool Insert(Var var, Locator *locator)
Definition: effects.h:318