Index: runtime/vm/object_set.h |
diff --git a/runtime/vm/object_set.h b/runtime/vm/object_set.h |
index cdc642f518b0f05ae2582a8f6e8123f802c411f9..8ba53bad1d1ee9bab0d11491cfaa20230c582a51 100644 |
--- a/runtime/vm/object_set.h |
+++ b/runtime/vm/object_set.h |
@@ -6,109 +6,86 @@ |
#define VM_OBJECT_SET_H_ |
#include "platform/utils.h" |
+#include "vm/bit_vector.h" |
#include "vm/globals.h" |
#include "vm/raw_object.h" |
+#include "vm/zone.h" |
namespace dart { |
-class ObjectSet { |
+class ObjectSetRegion : public ZoneAllocated { |
public: |
- ObjectSet() { |
- Init(0, 0); |
+ ObjectSetRegion(Zone* zone, uword start, uword end) |
+ : start_(start), |
+ end_(end), |
+ bit_vector_(zone, (end - start) >> kWordSizeLog2), |
+ next_(NULL) { |
} |
- ObjectSet(uword start, uword end) { |
- Init(start, end); |
+ bool ContainsAddress(uword address) { |
+ return address >= start_ && address < end_; |
} |
- ~ObjectSet() { |
- delete[] allocation_; |
+ intptr_t IndexForAddress(uword address) { |
+ ASSERT(Utils::IsAligned(address, kWordSize)); |
+ return (address - start_) >> kWordSizeLog2; |
} |
- void Init(uword start, uword end) { |
- start_ = start; |
- end_ = end; |
- ASSERT(start_ <= end_); |
- size_ = SizeFor((end_ - start_) >> kWordSizeLog2); |
- allocation_ = new uword[size_]; |
- const intptr_t skipped_bitfield_words = |
- (start >> kWordSizeLog2) / kBitsPerWord; |
- data_ = &allocation_[-skipped_bitfield_words]; |
- ASSERT(allocation_ == &data_[skipped_bitfield_words]); |
- Clear(); |
+ void AddObject(uword address) { |
+ bit_vector_.Add(IndexForAddress(address)); |
} |
- bool Contains(RawObject* raw_obj) const { |
- uword raw_addr = RawObject::ToAddr(raw_obj); |
- ASSERT(raw_addr >= start_); |
- ASSERT(raw_addr < end_); |
- uword i = raw_addr >> kWordSizeLog2; |
- uword mask = (static_cast<uword>(1) << (i % kBitsPerWord)); |
- return (data_[i / kBitsPerWord] & mask) != 0; |
+ bool ContainsObject(uword address) { |
+ return bit_vector_.Contains(IndexForAddress(address)); |
} |
- void Add(RawObject* raw_obj) { |
- uword raw_addr = RawObject::ToAddr(raw_obj); |
- ASSERT(raw_addr >= start_); |
- ASSERT(raw_addr < end_); |
- uword i = raw_addr >> kWordSizeLog2; |
- data_[i / kBitsPerWord] |= (static_cast<uword>(1) << (i % kBitsPerWord)); |
- min_ = Utils::Minimum(raw_addr, min_); |
- max_ = Utils::Maximum(raw_addr, max_); |
- } |
+ ObjectSetRegion* next() { return next_; } |
+ void set_next(ObjectSetRegion* region) { next_ = region; } |
- void Resize(uword start, uword end) { |
- if (start_ != start || end_ != end) { |
- delete[] allocation_; |
- Init(start, end); |
- } |
- } |
+ private: |
+ uword start_; |
+ uword end_; |
+ BitVector bit_vector_; |
+ ObjectSetRegion* next_; |
+}; |
- void Clear() { |
- memset(allocation_, 0, (size_ * sizeof(allocation_[0]))); |
- min_ = end_; |
- max_ = start_; |
- } |
+class ObjectSet : public ZoneAllocated { |
+ public: |
+ explicit ObjectSet(Zone* zone) : zone_(zone), head_(NULL) { } |
- void FastClear() { |
- uword i = min_ >> kWordSizeLog2; |
- memset(&data_[i / kBitsPerWord], |
- 0, |
- sizeof(uword) * SizeFor((max_ + 1 - min_) >> kWordSizeLog2)); |
- min_ = end_; |
- max_ = start_; |
+ void AddRegion(uword start, uword end) { |
+ ObjectSetRegion* region = new(zone_) ObjectSetRegion(zone_, start, end); |
+ region->set_next(head_); |
+ head_ = region; |
} |
- private: |
- static intptr_t SizeFor(intptr_t length) { |
- return 1 + ((length - 1) / kBitsPerWord); |
+ bool Contains(RawObject* raw_obj) const { |
+ uword raw_addr = RawObject::ToAddr(raw_obj); |
+ for (ObjectSetRegion* region = head_; |
zra
2016/09/16 22:30:22
How slow is this? I guess we'll have to monitor th
rmacnak
2016/09/16 22:39:49
I didn't see timeouts locally with another workspa
|
+ region != NULL; |
+ region = region->next()) { |
+ if (region->ContainsAddress(raw_addr)) { |
+ return region->ContainsObject(raw_addr); |
+ } |
+ } |
+ return false; |
} |
- // Biased data pointer aliased to allocation_. This value can be |
- // indexed without adjusting for the starting address of the heap. |
- uword* data_; |
- |
- // Allocated data pointer. |
- uword* allocation_; |
- |
- // Allocation size in uwords. |
- intptr_t size_; |
- |
- // Lowest possible heap address, inclusive. |
- uword start_; |
- |
- // Highest possible heap address, exclusive. |
- uword end_; |
- |
- // The inclusive minimum address set in this ObjectMap. |
- // Used by FastClear |
- uword min_; |
- |
- // The inclusive maximum address in this ObjectMap. |
- // Used by FastClear |
- uword max_; |
+ void Add(RawObject* raw_obj) { |
+ uword raw_addr = RawObject::ToAddr(raw_obj); |
+ for (ObjectSetRegion* region = head_; |
+ region != NULL; |
+ region = region->next()) { |
+ if (region->ContainsAddress(raw_addr)) { |
+ return region->AddObject(raw_addr); |
+ } |
+ } |
+ FATAL("Address not in any heap region"); |
+ } |
- DISALLOW_COPY_AND_ASSIGN(ObjectSet); |
+ private: |
+ Zone* zone_; |
+ ObjectSetRegion* head_; |
}; |
} // namespace dart |