blob: 6e2230c65ea5d3b2051a766aa62347c914cf61b9 [file] [log] [blame]
Leon Clarke4515c472010-02-03 11:58:03 +00001// Copyright 2010 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_DATAFLOW_H_
29#define V8_DATAFLOW_H_
30
Steve Block6ded16b2010-05-10 14:33:55 +010031#include "v8.h"
32
Leon Clarke4515c472010-02-03 11:58:03 +000033#include "ast.h"
Andrei Popescu31002712010-02-23 13:46:05 +000034#include "compiler.h"
Steve Block6ded16b2010-05-10 14:33:55 +010035#include "zone-inl.h"
Leon Clarke4515c472010-02-03 11:58:03 +000036
37namespace v8 {
38namespace internal {
39
Steve Block6ded16b2010-05-10 14:33:55 +010040// Forward declarations.
41class Node;
42
43class BitVector: public ZoneObject {
44 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +010045 // Iterator for the elements of this BitVector.
46 class Iterator BASE_EMBEDDED {
47 public:
48 explicit Iterator(BitVector* target)
49 : target_(target),
50 current_index_(0),
51 current_value_(target->data_[0]),
52 current_(-1) {
53 ASSERT(target->data_length_ > 0);
54 Advance();
55 }
56 ~Iterator() { }
Kristian Monsen80d68ea2010-09-08 11:05:35 +010057
Ben Murdochb0fe1622011-05-05 13:52:32 +010058 bool Done() const { return current_index_ >= target_->data_length_; }
59 void Advance();
60
61 int Current() const {
62 ASSERT(!Done());
63 return current_;
64 }
65
66 private:
67 uint32_t SkipZeroBytes(uint32_t val) {
68 while ((val & 0xFF) == 0) {
69 val >>= 8;
70 current_ += 8;
71 }
72 return val;
73 }
74 uint32_t SkipZeroBits(uint32_t val) {
75 while ((val & 0x1) == 0) {
76 val >>= 1;
77 current_++;
78 }
79 return val;
80 }
81
82 BitVector* target_;
83 int current_index_;
84 uint32_t current_value_;
85 int current_;
86
87 friend class BitVector;
88 };
89
90 explicit BitVector(int length)
91 : length_(length),
92 data_length_(SizeFor(length)),
93 data_(Zone::NewArray<uint32_t>(data_length_)) {
94 ASSERT(length > 0);
95 Clear();
Steve Block6ded16b2010-05-10 14:33:55 +010096 }
97
98 BitVector(const BitVector& other)
99 : length_(other.length()),
100 data_length_(SizeFor(length_)),
101 data_(Zone::NewArray<uint32_t>(data_length_)) {
102 CopyFrom(other);
103 }
104
Ben Murdochb0fe1622011-05-05 13:52:32 +0100105 static int SizeFor(int length) {
106 return 1 + ((length - 1) / 32);
Steve Block6ded16b2010-05-10 14:33:55 +0100107 }
108
109 BitVector& operator=(const BitVector& rhs) {
110 if (this != &rhs) CopyFrom(rhs);
111 return *this;
112 }
113
114 void CopyFrom(const BitVector& other) {
115 ASSERT(other.length() == length());
116 for (int i = 0; i < data_length_; i++) {
117 data_[i] = other.data_[i];
118 }
119 }
120
Ben Murdochb0fe1622011-05-05 13:52:32 +0100121 bool Contains(int i) const {
Steve Block6ded16b2010-05-10 14:33:55 +0100122 ASSERT(i >= 0 && i < length());
123 uint32_t block = data_[i / 32];
124 return (block & (1U << (i % 32))) != 0;
125 }
126
127 void Add(int i) {
128 ASSERT(i >= 0 && i < length());
129 data_[i / 32] |= (1U << (i % 32));
130 }
131
132 void Remove(int i) {
133 ASSERT(i >= 0 && i < length());
134 data_[i / 32] &= ~(1U << (i % 32));
135 }
136
137 void Union(const BitVector& other) {
138 ASSERT(other.length() == length());
139 for (int i = 0; i < data_length_; i++) {
140 data_[i] |= other.data_[i];
141 }
142 }
143
Ben Murdochb0fe1622011-05-05 13:52:32 +0100144 bool UnionIsChanged(const BitVector& other) {
145 ASSERT(other.length() == length());
146 bool changed = false;
147 for (int i = 0; i < data_length_; i++) {
148 uint32_t old_data = data_[i];
149 data_[i] |= other.data_[i];
150 if (data_[i] != old_data) changed = true;
151 }
152 return changed;
153 }
154
Steve Block6ded16b2010-05-10 14:33:55 +0100155 void Intersect(const BitVector& other) {
156 ASSERT(other.length() == length());
157 for (int i = 0; i < data_length_; i++) {
158 data_[i] &= other.data_[i];
159 }
160 }
161
162 void Subtract(const BitVector& other) {
163 ASSERT(other.length() == length());
164 for (int i = 0; i < data_length_; i++) {
165 data_[i] &= ~other.data_[i];
166 }
167 }
168
169 void Clear() {
170 for (int i = 0; i < data_length_; i++) {
171 data_[i] = 0;
172 }
173 }
174
175 bool IsEmpty() const {
176 for (int i = 0; i < data_length_; i++) {
177 if (data_[i] != 0) return false;
178 }
179 return true;
180 }
181
182 bool Equals(const BitVector& other) {
183 for (int i = 0; i < data_length_; i++) {
184 if (data_[i] != other.data_[i]) return false;
185 }
186 return true;
187 }
188
189 int length() const { return length_; }
190
191#ifdef DEBUG
192 void Print();
193#endif
194
195 private:
196 int length_;
197 int data_length_;
198 uint32_t* data_;
199};
200
201
Ben Murdochb0fe1622011-05-05 13:52:32 +0100202// An implementation of a sparse set whose elements are drawn from integers
203// in the range [0..universe_size[. It supports constant-time Contains,
204// destructive Add, and destructuve Remove operations and linear-time (in
205// the number of elements) destructive Union.
206class SparseSet: public ZoneObject {
207 public:
208 // Iterator for sparse set elements. Elements should not be added or
209 // removed during iteration.
210 class Iterator BASE_EMBEDDED {
211 public:
212 explicit Iterator(SparseSet* target) : target_(target), current_(0) {
213 ASSERT(++target->iterator_count_ > 0);
214 }
215 ~Iterator() {
216 ASSERT(target_->iterator_count_-- > 0);
217 }
218 bool Done() const { return current_ >= target_->dense_.length(); }
219 void Advance() {
220 ASSERT(!Done());
221 ++current_;
222 }
223 int Current() {
224 ASSERT(!Done());
225 return target_->dense_[current_];
226 }
227
228 private:
229 SparseSet* target_;
230 int current_;
231
232 friend class SparseSet;
233 };
234
235 explicit SparseSet(int universe_size)
236 : dense_(4),
237 sparse_(Zone::NewArray<int>(universe_size)) {
238#ifdef DEBUG
239 size_ = universe_size;
240 iterator_count_ = 0;
241#endif
242 }
243
244 bool Contains(int n) const {
245 ASSERT(0 <= n && n < size_);
246 int dense_index = sparse_[n];
247 return (0 <= dense_index) &&
248 (dense_index < dense_.length()) &&
249 (dense_[dense_index] == n);
250 }
251
252 void Add(int n) {
253 ASSERT(0 <= n && n < size_);
254 ASSERT(iterator_count_ == 0);
255 if (!Contains(n)) {
256 sparse_[n] = dense_.length();
257 dense_.Add(n);
258 }
259 }
260
261 void Remove(int n) {
262 ASSERT(0 <= n && n < size_);
263 ASSERT(iterator_count_ == 0);
264 if (Contains(n)) {
265 int dense_index = sparse_[n];
266 int last = dense_.RemoveLast();
267 if (dense_index < dense_.length()) {
268 dense_[dense_index] = last;
269 sparse_[last] = dense_index;
270 }
271 }
272 }
273
274 void Union(const SparseSet& other) {
275 for (int i = 0; i < other.dense_.length(); ++i) {
276 Add(other.dense_[i]);
277 }
278 }
279
280 private:
281 // The set is implemented as a pair of a growable dense list and an
282 // uninitialized sparse array.
283 ZoneList<int> dense_;
284 int* sparse_;
285#ifdef DEBUG
286 int size_;
287 int iterator_count_;
288#endif
289};
290
291
Steve Block6ded16b2010-05-10 14:33:55 +0100292// Simple fixed-capacity list-based worklist (managed as a queue) of
293// pointers to T.
294template<typename T>
295class WorkList BASE_EMBEDDED {
296 public:
297 // The worklist cannot grow bigger than size. We keep one item empty to
298 // distinguish between empty and full.
299 explicit WorkList(int size)
300 : capacity_(size + 1), head_(0), tail_(0), queue_(capacity_) {
301 for (int i = 0; i < capacity_; i++) queue_.Add(NULL);
302 }
303
304 bool is_empty() { return head_ == tail_; }
305
306 bool is_full() {
307 // The worklist is full if head is at 0 and tail is at capacity - 1:
308 // head == 0 && tail == capacity-1 ==> tail - head == capacity - 1
309 // or if tail is immediately to the left of head:
310 // tail+1 == head ==> tail - head == -1
311 int diff = tail_ - head_;
312 return (diff == -1 || diff == capacity_ - 1);
313 }
314
315 void Insert(T* item) {
316 ASSERT(!is_full());
317 queue_[tail_++] = item;
318 if (tail_ == capacity_) tail_ = 0;
319 }
320
321 T* Remove() {
322 ASSERT(!is_empty());
323 T* item = queue_[head_++];
324 if (head_ == capacity_) head_ = 0;
325 return item;
326 }
327
328 private:
329 int capacity_; // Including one empty slot.
330 int head_; // Where the first item is.
331 int tail_; // Where the next inserted item will go.
332 List<T*> queue_;
333};
334
335
Steve Block6ded16b2010-05-10 14:33:55 +0100336// Computes the set of assigned variables and annotates variables proxies
337// that are trivial sub-expressions and for-loops where the loop variable
338// is guaranteed to be a smi.
339class AssignedVariablesAnalyzer : public AstVisitor {
Andrei Popescu402d9372010-02-26 13:31:12 +0000340 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100341 static bool Analyze(CompilationInfo* info);
Andrei Popescu402d9372010-02-26 13:31:12 +0000342
343 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100344 AssignedVariablesAnalyzer(CompilationInfo* info, int bits);
345 bool Analyze();
346
Steve Block6ded16b2010-05-10 14:33:55 +0100347 Variable* FindSmiLoopVariable(ForStatement* stmt);
Andrei Popescu402d9372010-02-26 13:31:12 +0000348
Steve Block6ded16b2010-05-10 14:33:55 +0100349 int BitIndex(Variable* var);
Andrei Popescu402d9372010-02-26 13:31:12 +0000350
Steve Block6ded16b2010-05-10 14:33:55 +0100351 void RecordAssignedVar(Variable* var);
Andrei Popescu402d9372010-02-26 13:31:12 +0000352
Steve Block6ded16b2010-05-10 14:33:55 +0100353 void MarkIfTrivial(Expression* expr);
Andrei Popescu402d9372010-02-26 13:31:12 +0000354
Steve Block6ded16b2010-05-10 14:33:55 +0100355 // Visits an expression saving the accumulator before, clearing
356 // it before visting and restoring it after visiting.
357 void ProcessExpression(Expression* expr);
Andrei Popescu402d9372010-02-26 13:31:12 +0000358
359 // AST node visit functions.
360#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
361 AST_NODE_LIST(DECLARE_VISIT)
362#undef DECLARE_VISIT
363
Ben Murdochf87a2032010-10-22 12:50:53 +0100364 CompilationInfo* info_;
Andrei Popescu402d9372010-02-26 13:31:12 +0000365
Steve Block6ded16b2010-05-10 14:33:55 +0100366 // Accumulator for assigned variables set.
367 BitVector av_;
368
369 DISALLOW_COPY_AND_ASSIGN(AssignedVariablesAnalyzer);
Andrei Popescu402d9372010-02-26 13:31:12 +0000370};
371
372
Leon Clarke4515c472010-02-03 11:58:03 +0000373} } // namespace v8::internal
374
Andrei Popescu402d9372010-02-26 13:31:12 +0000375
Leon Clarke4515c472010-02-03 11:58:03 +0000376#endif // V8_DATAFLOW_H_