aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/zone/zone-handle-set.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/zone/zone-handle-set.h')
-rw-r--r--deps/v8/src/zone/zone-handle-set.h165
1 files changed, 165 insertions, 0 deletions
diff --git a/deps/v8/src/zone/zone-handle-set.h b/deps/v8/src/zone/zone-handle-set.h
new file mode 100644
index 0000000000..641c740abb
--- /dev/null
+++ b/deps/v8/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_