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
unique.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_HYDROGEN_UNIQUE_H_
29 #define V8_HYDROGEN_UNIQUE_H_
30 
31 #include "handles.h"
32 #include "objects.h"
33 #include "utils.h"
34 #include "zone.h"
35 
36 namespace v8 {
37 namespace internal {
38 
39 
40 template <typename T>
41 class UniqueSet;
42 
43 
44 // Represents a handle to an object on the heap, but with the additional
45 // ability of checking for equality and hashing without accessing the heap.
46 //
47 // Creating a Unique<T> requires first dereferencing the handle to obtain
48 // the address of the object, which is used as the hashcode and the basis for
49 // comparison. The object can be moved later by the GC, but comparison
50 // and hashing use the old address of the object, without dereferencing it.
51 //
52 // Careful! Comparison of two Uniques is only correct if both were created
53 // in the same "era" of GC or if at least one is a non-movable object.
54 template <typename T>
55 class Unique V8_FINAL {
56  public:
57  // TODO(titzer): make private and introduce a uniqueness scope.
58  explicit Unique(Handle<T> handle) {
59  if (handle.is_null()) {
60  raw_address_ = NULL;
61  } else {
62  // This is a best-effort check to prevent comparing Unique<T>'s created
63  // in different GC eras; we require heap allocation to be disallowed at
64  // creation time.
65  // NOTE: we currently consider maps to be non-movable, so no special
66  // assurance is required for creating a Unique<Map>.
67  // TODO(titzer): other immortable immovable objects are also fine.
68  ASSERT(!AllowHeapAllocation::IsAllowed() || handle->IsMap());
69  raw_address_ = reinterpret_cast<Address>(*handle);
70  ASSERT_NE(raw_address_, NULL); // Non-null should imply non-zero address.
71  }
72  handle_ = handle;
73  }
74 
75  // TODO(titzer): this is a hack to migrate to Unique<T> incrementally.
77  : raw_address_(raw_address), handle_(handle) { }
78 
79  // Constructor for handling automatic up casting.
80  // Eg. Unique<JSFunction> can be passed when Unique<Object> is expected.
81  template <class S> Unique(Unique<S> uniq) {
82 #ifdef DEBUG
83  T* a = NULL;
84  S* b = NULL;
85  a = b; // Fake assignment to enforce type checks.
86  USE(a);
87 #endif
88  raw_address_ = uniq.raw_address_;
89  handle_ = uniq.handle_;
90  }
91 
92  template <typename U>
93  inline bool operator==(const Unique<U>& other) const {
94  ASSERT(IsInitialized() && other.IsInitialized());
95  return raw_address_ == other.raw_address_;
96  }
97 
98  template <typename U>
99  inline bool operator!=(const Unique<U>& other) const {
100  ASSERT(IsInitialized() && other.IsInitialized());
101  return raw_address_ != other.raw_address_;
102  }
103 
104  inline intptr_t Hashcode() const {
105  ASSERT(IsInitialized());
106  return reinterpret_cast<intptr_t>(raw_address_);
107  }
108 
109  inline bool IsNull() const {
110  ASSERT(IsInitialized());
111  return raw_address_ == NULL;
112  }
113 
114  inline bool IsKnownGlobal(void* global) const {
115  ASSERT(IsInitialized());
116  return raw_address_ == reinterpret_cast<Address>(global);
117  }
118 
119  inline Handle<T> handle() const {
120  return handle_;
121  }
122 
123  template <class S> static Unique<T> cast(Unique<S> that) {
124  return Unique<T>(that.raw_address_, Handle<T>::cast(that.handle_));
125  }
126 
127  inline bool IsInitialized() const {
128  return raw_address_ != NULL || handle_.is_null();
129  }
130 
131  // TODO(titzer): this is a hack to migrate to Unique<T> incrementally.
133  return Unique<T>(reinterpret_cast<Address>(NULL), handle);
134  }
135 
136  static Unique<T> CreateImmovable(Handle<T> handle) {
137  return Unique<T>(reinterpret_cast<Address>(*handle), handle);
138  }
139 
140  friend class UniqueSet<T>; // Uses internal details for speed.
141  template <class U>
142  friend class Unique; // For comparing raw_address values.
143 
144  private:
145  Unique<T>() : raw_address_(NULL) { }
146 
147  Address raw_address_;
148  Handle<T> handle_;
149 
150  friend class SideEffectsTracker;
151 };
152 
153 
154 template <typename T>
155 class UniqueSet V8_FINAL : public ZoneObject {
156  public:
157  // Constructor. A new set will be empty.
158  UniqueSet() : size_(0), capacity_(0), array_(NULL) { }
159 
160  // Add a new element to this unique set. Mutates this set. O(|this|).
161  void Add(Unique<T> uniq, Zone* zone) {
162  ASSERT(uniq.IsInitialized());
163  // Keep the set sorted by the {raw_address} of the unique elements.
164  for (int i = 0; i < size_; i++) {
165  if (array_[i] == uniq) return;
166  if (array_[i].raw_address_ > uniq.raw_address_) {
167  // Insert in the middle.
168  Grow(size_ + 1, zone);
169  for (int j = size_ - 1; j >= i; j--) array_[j + 1] = array_[j];
170  array_[i] = uniq;
171  size_++;
172  return;
173  }
174  }
175  // Append the element to the the end.
176  Grow(size_ + 1, zone);
177  array_[size_++] = uniq;
178  }
179 
180  // Remove an element from this set. Mutates this set. O(|this|)
181  void Remove(Unique<T> uniq) {
182  for (int i = 0; i < size_; i++) {
183  if (array_[i] == uniq) {
184  while (++i < size_) array_[i - 1] = array_[i];
185  size_--;
186  return;
187  }
188  }
189  }
190 
191  // Compare this set against another set. O(|this|).
192  bool Equals(UniqueSet<T>* that) const {
193  if (that->size_ != this->size_) return false;
194  for (int i = 0; i < this->size_; i++) {
195  if (this->array_[i] != that->array_[i]) return false;
196  }
197  return true;
198  }
199 
200  // Check whether this set contains the given element. O(|this|)
201  // TODO(titzer): use binary search for large sets to make this O(log|this|)
202  template <typename U>
203  bool Contains(Unique<U> elem) const {
204  for (int i = 0; i < size_; i++) {
205  if (this->array_[i] == elem) return true;
206  }
207  return false;
208  }
209 
210  // Check if this set is a subset of the given set. O(|this| + |that|).
211  bool IsSubset(UniqueSet<T>* that) const {
212  if (that->size_ < this->size_) return false;
213  int j = 0;
214  for (int i = 0; i < this->size_; i++) {
215  Unique<T> sought = this->array_[i];
216  while (true) {
217  if (sought == that->array_[j++]) break;
218  // Fail whenever there are more elements in {this} than {that}.
219  if ((this->size_ - i) > (that->size_ - j)) return false;
220  }
221  }
222  return true;
223  }
224 
225  // Returns a new set representing the intersection of this set and the other.
226  // O(|this| + |that|).
227  UniqueSet<T>* Intersect(UniqueSet<T>* that, Zone* zone) const {
228  if (that->size_ == 0 || this->size_ == 0) return new(zone) UniqueSet<T>();
229 
230  UniqueSet<T>* out = new(zone) UniqueSet<T>();
231  out->Grow(Min(this->size_, that->size_), zone);
232 
233  int i = 0, j = 0, k = 0;
234  while (i < this->size_ && j < that->size_) {
235  Unique<T> a = this->array_[i];
236  Unique<T> b = that->array_[j];
237  if (a == b) {
238  out->array_[k++] = a;
239  i++;
240  j++;
241  } else if (a.raw_address_ < b.raw_address_) {
242  i++;
243  } else {
244  j++;
245  }
246  }
247 
248  out->size_ = k;
249  return out;
250  }
251 
252  // Returns a new set representing the union of this set and the other.
253  // O(|this| + |that|).
254  UniqueSet<T>* Union(UniqueSet<T>* that, Zone* zone) const {
255  if (that->size_ == 0) return this->Copy(zone);
256  if (this->size_ == 0) return that->Copy(zone);
257 
258  UniqueSet<T>* out = new(zone) UniqueSet<T>();
259  out->Grow(this->size_ + that->size_, zone);
260 
261  int i = 0, j = 0, k = 0;
262  while (i < this->size_ && j < that->size_) {
263  Unique<T> a = this->array_[i];
264  Unique<T> b = that->array_[j];
265  if (a == b) {
266  out->array_[k++] = a;
267  i++;
268  j++;
269  } else if (a.raw_address_ < b.raw_address_) {
270  out->array_[k++] = a;
271  i++;
272  } else {
273  out->array_[k++] = b;
274  j++;
275  }
276  }
277 
278  while (i < this->size_) out->array_[k++] = this->array_[i++];
279  while (j < that->size_) out->array_[k++] = that->array_[j++];
280 
281  out->size_ = k;
282  return out;
283  }
284 
285  // Makes an exact copy of this set. O(|this|).
286  UniqueSet<T>* Copy(Zone* zone) const {
287  UniqueSet<T>* copy = new(zone) UniqueSet<T>();
288  copy->size_ = this->size_;
289  copy->capacity_ = this->size_;
290  copy->array_ = zone->NewArray<Unique<T> >(this->size_);
291  memcpy(copy->array_, this->array_, this->size_ * sizeof(Unique<T>));
292  return copy;
293  }
294 
295  void Clear() {
296  size_ = 0;
297  }
298 
299  inline int size() const {
300  return size_;
301  }
302 
303  inline Unique<T> at(int index) const {
304  ASSERT(index >= 0 && index < size_);
305  return array_[index];
306  }
307 
308  private:
309  // These sets should be small, since operations are implemented with simple
310  // linear algorithms. Enforce a maximum size.
311  static const int kMaxCapacity = 65535;
312 
313  uint16_t size_;
314  uint16_t capacity_;
315  Unique<T>* array_;
316 
317  // Grow the size of internal storage to be at least {size} elements.
318  void Grow(int size, Zone* zone) {
319  CHECK(size < kMaxCapacity); // Enforce maximum size.
320  if (capacity_ < size) {
321  int new_capacity = 2 * capacity_ + size;
322  if (new_capacity > kMaxCapacity) new_capacity = kMaxCapacity;
323  Unique<T>* new_array = zone->NewArray<Unique<T> >(new_capacity);
324  if (size_ > 0) {
325  memcpy(new_array, array_, size_ * sizeof(Unique<T>));
326  }
327  capacity_ = new_capacity;
328  array_ = new_array;
329  }
330  }
331 };
332 
333 
334 } } // namespace v8::internal
335 
336 #endif // V8_HYDROGEN_UNIQUE_H_
byte * Address
Definition: globals.h:186
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
UniqueSet< T > * Copy(Zone *zone) const
Definition: unique.h:286
Unique(Address raw_address, Handle< T > handle)
Definition: unique.h:76
void Remove(Unique< T > uniq)
Definition: unique.h:181
static Unique< T > CreateImmovable(Handle< T > handle)
Definition: unique.h:136
bool IsSubset(UniqueSet< T > *that) const
Definition: unique.h:211
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
Handle< T > handle() const
Definition: unique.h:119
#define ASSERT(condition)
Definition: checks.h:329
static Unique< T > cast(Unique< S > that)
Definition: unique.h:123
unsigned short uint16_t
Definition: unicode.cc:46
#define CHECK(condition)
Definition: checks.h:75
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 size
Definition: flags.cc:211
bool operator==(const Unique< U > &other) const
Definition: unique.h:93
int size() const
Definition: unique.h:299
Unique(Unique< S > uniq)
Definition: unique.h:81
T * NewArray(int length)
Definition: zone-inl.h:93
#define T(name, string, precedence)
Definition: token.cc:48
bool IsNull() const
Definition: unique.h:109
UniqueSet< T > * Union(UniqueSet< T > *that, Zone *zone) const
Definition: unique.h:254
bool IsKnownGlobal(void *global) const
Definition: unique.h:114
bool is_null() const
Definition: handles.h:81
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:103
bool operator!=(const Unique< U > &other) const
Definition: unique.h:99
bool Equals(UniqueSet< T > *that) const
Definition: unique.h:192
void USE(T)
Definition: globals.h:341
#define ASSERT_NE(v1, v2)
Definition: checks.h:331
bool Contains(Unique< U > elem) const
Definition: unique.h:203
static Unique< T > CreateUninitialized(Handle< T > handle)
Definition: unique.h:132
Unique(Handle< T > handle)
Definition: unique.h:58
intptr_t Hashcode() const
Definition: unique.h:104
T Min(T a, T b)
Definition: utils.h:234
UniqueSet< T > * Intersect(UniqueSet< T > *that, Zone *zone) const
Definition: unique.h:227
Unique< T > at(int index) const
Definition: unique.h:303
void Add(Unique< T > uniq, Zone *zone)
Definition: unique.h:161
bool IsInitialized() const
Definition: unique.h:127