#include "src/handles.h"
#include "src/objects.h"
+#include "src/string-stream.h"
#include "src/utils.h"
#include "src/zone.h"
// Careful! Comparison of two Uniques is only correct if both were created
// in the same "era" of GC or if at least one is a non-movable object.
template <typename T>
-class Unique V8_FINAL {
+class Unique {
public:
// TODO(titzer): make private and introduce a uniqueness scope.
explicit Unique(Handle<T> handle) {
// NOTE: we currently consider maps to be non-movable, so no special
// assurance is required for creating a Unique<Map>.
// TODO(titzer): other immortable immovable objects are also fine.
- ASSERT(!AllowHeapAllocation::IsAllowed() || handle->IsMap());
+ DCHECK(!AllowHeapAllocation::IsAllowed() || handle->IsMap());
raw_address_ = reinterpret_cast<Address>(*handle);
- ASSERT_NE(raw_address_, NULL); // Non-null should imply non-zero address.
+ DCHECK_NE(raw_address_, NULL); // Non-null should imply non-zero address.
}
handle_ = handle;
}
template <typename U>
inline bool operator==(const Unique<U>& other) const {
- ASSERT(IsInitialized() && other.IsInitialized());
+ DCHECK(IsInitialized() && other.IsInitialized());
return raw_address_ == other.raw_address_;
}
template <typename U>
inline bool operator!=(const Unique<U>& other) const {
- ASSERT(IsInitialized() && other.IsInitialized());
+ DCHECK(IsInitialized() && other.IsInitialized());
return raw_address_ != other.raw_address_;
}
inline intptr_t Hashcode() const {
- ASSERT(IsInitialized());
+ DCHECK(IsInitialized());
return reinterpret_cast<intptr_t>(raw_address_);
}
inline bool IsNull() const {
- ASSERT(IsInitialized());
+ DCHECK(IsInitialized());
return raw_address_ == NULL;
}
inline bool IsKnownGlobal(void* global) const {
- ASSERT(IsInitialized());
+ DCHECK(IsInitialized());
return raw_address_ == reinterpret_cast<Address>(global);
}
friend class UniqueSet<T>; // Uses internal details for speed.
template <class U>
friend class Unique; // For comparing raw_address values.
+ template <class U>
+ friend class PrintableUnique; // For automatic up casting.
- private:
+ protected:
Unique<T>() : raw_address_(NULL) { }
Address raw_address_;
};
+// TODO(danno): At some point if all of the uses of Unique end up using
+// PrintableUnique, then we should merge PrintableUnique into Unique and
+// predicate generating the printable string on a "am I tracing" check.
+template <class T>
+class PrintableUnique : public Unique<T> {
+ public:
+ // TODO(titzer): make private and introduce a uniqueness scope.
+ explicit PrintableUnique(Zone* zone, Handle<T> handle) : Unique<T>(handle) {
+ InitializeString(zone);
+ }
+
+ // TODO(titzer): this is a hack to migrate to Unique<T> incrementally.
+ PrintableUnique(Zone* zone, Address raw_address, Handle<T> handle)
+ : Unique<T>(raw_address, handle) {
+ InitializeString(zone);
+ }
+
+ // Constructor for handling automatic up casting.
+ // Eg. PrintableUnique<JSFunction> can be passed when PrintableUnique<Object>
+ // is expected.
+ template <class S>
+ PrintableUnique(PrintableUnique<S> uniq) // NOLINT
+ : Unique<T>(Handle<T>()) {
+#ifdef DEBUG
+ T* a = NULL;
+ S* b = NULL;
+ a = b; // Fake assignment to enforce type checks.
+ USE(a);
+#endif
+ this->raw_address_ = uniq.raw_address_;
+ this->handle_ = uniq.handle_;
+ string_ = uniq.string();
+ }
+
+ // TODO(titzer): this is a hack to migrate to Unique<T> incrementally.
+ static PrintableUnique<T> CreateUninitialized(Zone* zone, Handle<T> handle) {
+ return PrintableUnique<T>(zone, reinterpret_cast<Address>(NULL), handle);
+ }
+
+ static PrintableUnique<T> CreateImmovable(Zone* zone, Handle<T> handle) {
+ return PrintableUnique<T>(zone, reinterpret_cast<Address>(*handle), handle);
+ }
+
+ const char* string() { return string_; }
+
+ private:
+ const char* string_;
+
+ void InitializeString(Zone* zone) {
+ // The stringified version of the parameter must be calculated when the
+ // Operator is constructed to avoid accessing the heap.
+ HeapStringAllocator temp_allocator;
+ StringStream stream(&temp_allocator);
+ this->handle_->ShortPrint(&stream);
+ SmartArrayPointer<const char> desc_string = stream.ToCString();
+ const char* desc_chars = desc_string.get();
+ int length = static_cast<int>(strlen(desc_chars));
+ char* desc_copy = zone->NewArray<char>(length + 1);
+ memcpy(desc_copy, desc_chars, length + 1);
+ string_ = desc_copy;
+ }
+};
+
+
template <typename T>
class UniqueSet V8_FINAL : public ZoneObject {
public:
UniqueSet(int capacity, Zone* zone)
: size_(0), capacity_(capacity),
array_(zone->NewArray<Unique<T> >(capacity)) {
- ASSERT(capacity <= kMaxCapacity);
+ DCHECK(capacity <= kMaxCapacity);
}
// Singleton constructor.
// Add a new element to this unique set. Mutates this set. O(|this|).
void Add(Unique<T> uniq, Zone* zone) {
- ASSERT(uniq.IsInitialized());
+ DCHECK(uniq.IsInitialized());
// Keep the set sorted by the {raw_address} of the unique elements.
for (int i = 0; i < size_; i++) {
if (array_[i] == uniq) return;
}
inline Unique<T> at(int index) const {
- ASSERT(index >= 0 && index < size_);
+ DCHECK(index >= 0 && index < size_);
return array_[index];
}
}
};
-
} } // namespace v8::internal
#endif // V8_HYDROGEN_UNIQUE_H_