OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_HYDROGEN_UNIQUE_H_ | 5 #ifndef V8_HYDROGEN_UNIQUE_H_ |
6 #define V8_HYDROGEN_UNIQUE_H_ | 6 #define V8_HYDROGEN_UNIQUE_H_ |
7 | 7 |
8 #include "src/handles.h" | 8 #include "src/handles.h" |
9 #include "src/objects.h" | 9 #include "src/objects.h" |
| 10 #include "src/string-stream.h" |
10 #include "src/utils.h" | 11 #include "src/utils.h" |
11 #include "src/zone.h" | 12 #include "src/zone.h" |
12 | 13 |
13 namespace v8 { | 14 namespace v8 { |
14 namespace internal { | 15 namespace internal { |
15 | 16 |
16 | 17 |
17 template <typename T> | 18 template <typename T> |
18 class UniqueSet; | 19 class UniqueSet; |
19 | 20 |
20 | 21 |
21 // Represents a handle to an object on the heap, but with the additional | 22 // Represents a handle to an object on the heap, but with the additional |
22 // ability of checking for equality and hashing without accessing the heap. | 23 // ability of checking for equality and hashing without accessing the heap. |
23 // | 24 // |
24 // Creating a Unique<T> requires first dereferencing the handle to obtain | 25 // Creating a Unique<T> requires first dereferencing the handle to obtain |
25 // the address of the object, which is used as the hashcode and the basis for | 26 // the address of the object, which is used as the hashcode and the basis for |
26 // comparison. The object can be moved later by the GC, but comparison | 27 // comparison. The object can be moved later by the GC, but comparison |
27 // and hashing use the old address of the object, without dereferencing it. | 28 // and hashing use the old address of the object, without dereferencing it. |
28 // | 29 // |
29 // Careful! Comparison of two Uniques is only correct if both were created | 30 // Careful! Comparison of two Uniques is only correct if both were created |
30 // in the same "era" of GC or if at least one is a non-movable object. | 31 // in the same "era" of GC or if at least one is a non-movable object. |
31 template <typename T> | 32 template <typename T> |
32 class Unique V8_FINAL { | 33 class Unique { |
33 public: | 34 public: |
34 // TODO(titzer): make private and introduce a uniqueness scope. | 35 // TODO(titzer): make private and introduce a uniqueness scope. |
35 explicit Unique(Handle<T> handle) { | 36 explicit Unique(Handle<T> handle) { |
36 if (handle.is_null()) { | 37 if (handle.is_null()) { |
37 raw_address_ = NULL; | 38 raw_address_ = NULL; |
38 } else { | 39 } else { |
39 // This is a best-effort check to prevent comparing Unique<T>'s created | 40 // This is a best-effort check to prevent comparing Unique<T>'s created |
40 // in different GC eras; we require heap allocation to be disallowed at | 41 // in different GC eras; we require heap allocation to be disallowed at |
41 // creation time. | 42 // creation time. |
42 // NOTE: we currently consider maps to be non-movable, so no special | 43 // NOTE: we currently consider maps to be non-movable, so no special |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 return Unique<T>(reinterpret_cast<Address>(NULL), handle); | 111 return Unique<T>(reinterpret_cast<Address>(NULL), handle); |
111 } | 112 } |
112 | 113 |
113 static Unique<T> CreateImmovable(Handle<T> handle) { | 114 static Unique<T> CreateImmovable(Handle<T> handle) { |
114 return Unique<T>(reinterpret_cast<Address>(*handle), handle); | 115 return Unique<T>(reinterpret_cast<Address>(*handle), handle); |
115 } | 116 } |
116 | 117 |
117 friend class UniqueSet<T>; // Uses internal details for speed. | 118 friend class UniqueSet<T>; // Uses internal details for speed. |
118 template <class U> | 119 template <class U> |
119 friend class Unique; // For comparing raw_address values. | 120 friend class Unique; // For comparing raw_address values. |
| 121 template <class U> |
| 122 friend class PrintableUnique; // For automatic up casting. |
120 | 123 |
121 private: | 124 protected: |
122 Unique<T>() : raw_address_(NULL) { } | 125 Unique<T>() : raw_address_(NULL) { } |
123 | 126 |
124 Address raw_address_; | 127 Address raw_address_; |
125 Handle<T> handle_; | 128 Handle<T> handle_; |
126 | 129 |
127 friend class SideEffectsTracker; | 130 friend class SideEffectsTracker; |
128 }; | 131 }; |
129 | 132 |
130 | 133 |
| 134 // TODO(danno): At some point if all of the uses of Unique end up using |
| 135 // PrintableUnique, then we should merge PrintableUnique into Unique and |
| 136 // predicate generating the printable string on a "am I tracing" check. |
| 137 template <class T> |
| 138 class PrintableUnique : public Unique<T> { |
| 139 public: |
| 140 // TODO(titzer): make private and introduce a uniqueness scope. |
| 141 explicit PrintableUnique(Zone* zone, Handle<T> handle) : Unique<T>(handle) { |
| 142 InitializeString(zone); |
| 143 } |
| 144 |
| 145 // TODO(titzer): this is a hack to migrate to Unique<T> incrementally. |
| 146 PrintableUnique(Zone* zone, Address raw_address, Handle<T> handle) |
| 147 : Unique<T>(raw_address, handle) { |
| 148 InitializeString(zone); |
| 149 } |
| 150 |
| 151 // Constructor for handling automatic up casting. |
| 152 // Eg. PrintableUnique<JSFunction> can be passed when PrintableUnique<Object> |
| 153 // is expected. |
| 154 template <class S> |
| 155 PrintableUnique(PrintableUnique<S> uniq) // NOLINT |
| 156 : Unique<T>(Handle<T>()) { |
| 157 #ifdef DEBUG |
| 158 T* a = NULL; |
| 159 S* b = NULL; |
| 160 a = b; // Fake assignment to enforce type checks. |
| 161 USE(a); |
| 162 #endif |
| 163 this->raw_address_ = uniq.raw_address_; |
| 164 this->handle_ = uniq.handle_; |
| 165 string_ = uniq.string(); |
| 166 } |
| 167 |
| 168 // TODO(titzer): this is a hack to migrate to Unique<T> incrementally. |
| 169 static PrintableUnique<T> CreateUninitialized(Zone* zone, Handle<T> handle) { |
| 170 return PrintableUnique<T>(zone, reinterpret_cast<Address>(NULL), handle); |
| 171 } |
| 172 |
| 173 static PrintableUnique<T> CreateImmovable(Zone* zone, Handle<T> handle) { |
| 174 return PrintableUnique<T>(zone, reinterpret_cast<Address>(*handle), handle); |
| 175 } |
| 176 |
| 177 const char* string() { return string_; } |
| 178 |
| 179 private: |
| 180 const char* string_; |
| 181 |
| 182 void InitializeString(Zone* zone) { |
| 183 // The stringified version of the parameter must be calculated when the |
| 184 // Operator is constructed to avoid accessing the heap. |
| 185 HeapStringAllocator temp_allocator; |
| 186 StringStream stream(&temp_allocator); |
| 187 this->handle_->ShortPrint(&stream); |
| 188 SmartArrayPointer<const char> desc_string = stream.ToCString(); |
| 189 const char* desc_chars = desc_string.get(); |
| 190 int length = strlen(desc_chars); |
| 191 char* desc_copy = zone->NewArray<char>(length + 1); |
| 192 memcpy(desc_copy, desc_chars, length + 1); |
| 193 string_ = desc_copy; |
| 194 } |
| 195 }; |
| 196 |
| 197 |
131 template <typename T> | 198 template <typename T> |
132 class UniqueSet V8_FINAL : public ZoneObject { | 199 class UniqueSet V8_FINAL : public ZoneObject { |
133 public: | 200 public: |
134 // Constructor. A new set will be empty. | 201 // Constructor. A new set will be empty. |
135 UniqueSet() : size_(0), capacity_(0), array_(NULL) { } | 202 UniqueSet() : size_(0), capacity_(0), array_(NULL) { } |
136 | 203 |
137 // Capacity constructor. A new set will be empty. | 204 // Capacity constructor. A new set will be empty. |
138 UniqueSet(int capacity, Zone* zone) | 205 UniqueSet(int capacity, Zone* zone) |
139 : size_(0), capacity_(capacity), | 206 : size_(0), capacity_(capacity), |
140 array_(zone->NewArray<Unique<T> >(capacity)) { | 207 array_(zone->NewArray<Unique<T> >(capacity)) { |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 Unique<T>* new_array = zone->NewArray<Unique<T> >(new_capacity); | 401 Unique<T>* new_array = zone->NewArray<Unique<T> >(new_capacity); |
335 if (size_ > 0) { | 402 if (size_ > 0) { |
336 memcpy(new_array, array_, size_ * sizeof(Unique<T>)); | 403 memcpy(new_array, array_, size_ * sizeof(Unique<T>)); |
337 } | 404 } |
338 capacity_ = new_capacity; | 405 capacity_ = new_capacity; |
339 array_ = new_array; | 406 array_ = new_array; |
340 } | 407 } |
341 } | 408 } |
342 }; | 409 }; |
343 | 410 |
344 | |
345 } } // namespace v8::internal | 411 } } // namespace v8::internal |
346 | 412 |
347 #endif // V8_HYDROGEN_UNIQUE_H_ | 413 #endif // V8_HYDROGEN_UNIQUE_H_ |
OLD | NEW |