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