Index: src/zone/zone-handle-set.h |
diff --git a/src/zone/zone-handle-set.h b/src/zone/zone-handle-set.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..641c740abbb7e123330d7b771bf06fbc32650ad9 |
--- /dev/null |
+++ b/src/zone/zone-handle-set.h |
@@ -0,0 +1,165 @@ |
+// Copyright 2016 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef V8_ZONE_ZONE_HANDLE_SET_H_ |
+#define V8_ZONE_ZONE_HANDLE_SET_H_ |
+ |
+#include "src/handles.h" |
+#include "src/zone/zone.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+template <typename T> |
+class ZoneHandleSet final { |
+ public: |
+ ZoneHandleSet() : data_(kEmptyTag) {} |
+ explicit ZoneHandleSet(Handle<T> handle) |
+ : data_(bit_cast<intptr_t>(handle.address()) | kSingletonTag) { |
+ DCHECK(IsAligned(bit_cast<intptr_t>(handle.address()), kPointerAlignment)); |
+ } |
+ |
+ bool is_empty() const { return data_ == kEmptyTag; } |
+ |
+ size_t size() const { |
+ if ((data_ & kTagMask) == kEmptyTag) return 0; |
+ if ((data_ & kTagMask) == kSingletonTag) return 1; |
+ return list()->length(); |
+ } |
+ |
+ Handle<T> at(size_t i) const { |
+ DCHECK_NE(kEmptyTag, data_ & kTagMask); |
+ if ((data_ & kTagMask) == kSingletonTag) { |
+ DCHECK_EQ(0u, i); |
+ return Handle<T>(singleton()); |
+ } |
+ return Handle<T>(list()->at(static_cast<int>(i))); |
+ } |
+ |
+ Handle<T> operator[](size_t i) const { return at(i); } |
+ |
+ void insert(Handle<T> handle, Zone* zone) { |
+ T** const value = bit_cast<T**>(handle.address()); |
+ DCHECK(IsAligned(bit_cast<intptr_t>(value), kPointerAlignment)); |
+ if ((data_ & kTagMask) == kEmptyTag) { |
+ data_ = bit_cast<intptr_t>(value) | kSingletonTag; |
+ } else if ((data_ & kTagMask) == kSingletonTag) { |
+ if (singleton() == value) return; |
+ List* list = new (zone) List(2, zone); |
+ if (singleton() < value) { |
+ list->Add(singleton(), zone); |
+ list->Add(value, zone); |
+ } else { |
+ list->Add(value, zone); |
+ list->Add(singleton(), zone); |
+ } |
+ DCHECK(IsAligned(bit_cast<intptr_t>(list), kPointerAlignment)); |
+ data_ = bit_cast<intptr_t>(list) | kListTag; |
+ } else { |
+ DCHECK_EQ(kListTag, data_ & kTagMask); |
+ List const* const old_list = list(); |
+ for (int i = 0; i < old_list->length(); ++i) { |
+ if (old_list->at(i) == value) return; |
+ if (old_list->at(i) > value) break; |
+ } |
+ List* new_list = new (zone) List(old_list->length() + 1, zone); |
+ int i = 0; |
+ for (; i < old_list->length(); ++i) { |
+ if (old_list->at(i) > value) break; |
+ new_list->Add(old_list->at(i), zone); |
+ } |
+ new_list->Add(value, zone); |
+ for (; i < old_list->length(); ++i) { |
+ new_list->Add(old_list->at(i), zone); |
+ } |
+ DCHECK_EQ(old_list->length() + 1, new_list->length()); |
+ DCHECK(IsAligned(bit_cast<intptr_t>(new_list), kPointerAlignment)); |
+ data_ = bit_cast<intptr_t>(new_list) | kListTag; |
+ } |
+ } |
+ |
+ bool contains(ZoneHandleSet<T> const& other) const { |
+ if (data_ == other.data_) return true; |
+ if (data_ == kEmptyTag) return false; |
+ if (other.data_ == kEmptyTag) return true; |
+ if ((data_ & kTagMask) == kSingletonTag) return false; |
+ DCHECK_EQ(kListTag, data_ & kTagMask); |
+ if ((other.data_ & kTagMask) == kSingletonTag) { |
+ return list()->Contains(other.singleton()); |
+ } |
+ DCHECK_EQ(kListTag, other.data_ & kTagMask); |
+ // TODO(bmeurer): Optimize this case. |
+ for (int i = 0; i < other.list()->length(); ++i) { |
+ if (!list()->Contains(other.list()->at(i))) return false; |
+ } |
+ return true; |
+ } |
+ |
+ void remove(Handle<T> handle, Zone* zone) { |
+ // TODO(bmeurer): Optimize this case. |
+ ZoneHandleSet<T> that; |
+ for (size_t i = 0; i < size(); ++i) { |
+ Handle<T> value = at(i); |
+ if (value.address() != handle.address()) { |
+ that.insert(value, zone); |
+ } |
+ } |
+ std::swap(*this, that); |
+ } |
+ |
+ friend bool operator==(ZoneHandleSet<T> const& lhs, |
+ ZoneHandleSet<T> const& rhs) { |
+ if (lhs.data_ == rhs.data_) return true; |
+ if ((lhs.data_ & kTagMask) == kListTag && |
+ (rhs.data_ & kTagMask) == kListTag) { |
+ List const* const lhs_list = lhs.list(); |
+ List const* const rhs_list = rhs.list(); |
+ if (lhs_list->length() == rhs_list->length()) { |
+ for (int i = 0; i < lhs_list->length(); ++i) { |
+ if (lhs_list->at(i) != rhs_list->at(i)) return false; |
+ } |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ friend bool operator!=(ZoneHandleSet<T> const& lhs, |
+ ZoneHandleSet<T> const& rhs) { |
+ return !(lhs == rhs); |
+ } |
+ |
+ friend size_t hash_value(ZoneHandleSet<T> const& set) { |
+ return static_cast<size_t>(set.data_); |
+ } |
+ |
+ private: |
+ typedef ZoneList<T**> List; |
+ |
+ List const* list() const { |
+ DCHECK_EQ(kListTag, data_ & kTagMask); |
+ return bit_cast<List const*>(data_ - kListTag); |
+ } |
+ |
+ T** singleton() const { |
+ DCHECK_EQ(kSingletonTag, data_ & kTagMask); |
+ return bit_cast<T**>(data_ - kSingletonTag); |
+ } |
+ |
+ enum Tag : intptr_t { |
+ kSingletonTag = 0, |
+ kEmptyTag = 1, |
+ kListTag = 2, |
+ kTagMask = 3 |
+ }; |
+ |
+ STATIC_ASSERT(kTagMask < kPointerAlignment); |
+ |
+ intptr_t data_; |
+}; |
+ |
+} // namespace internal |
+} // namespace v8 |
+ |
+#endif // V8_ZONE_ZONE_HANDLE_SET_H_ |