Index: third_party/WebKit/Source/platform/heap/Handle.h |
diff --git a/third_party/WebKit/Source/platform/heap/Handle.h b/third_party/WebKit/Source/platform/heap/Handle.h |
index b5e0eb399a1ed538ee1418d8a14089c51250026a..ab8953b963a4292a895679463a62b03e311a9bf4 100644 |
--- a/third_party/WebKit/Source/platform/heap/Handle.h |
+++ b/third_party/WebKit/Source/platform/heap/Handle.h |
@@ -656,6 +656,24 @@ public: |
} |
}; |
+template<typename T, bool = IsGarbageCollectedMixin<T>::value> class GCMixinTrait; |
+template<typename T> |
+class GCMixinTrait<T, true> { |
+public: |
+ static HeapObjectHeader* heapObjectHeader(T* obj) |
+ { |
+ return obj->heapObjectHeader(); |
+ } |
+}; |
+template<typename T> |
+class GCMixinTrait<T, false> { |
+public: |
+ static HeapObjectHeader* heapObjectHeader(T* obj) |
+ { |
+ return HeapObjectHeader::fromPayload(obj); |
+ } |
+}; |
+ |
// Members are used in classes to contain strong pointers to other oilpan heap |
// allocated objects. |
// All Member fields of a class must be traced in the class' trace method. |
@@ -666,10 +684,12 @@ class Member { |
public: |
Member() : m_raw(nullptr) |
{ |
+ checkPointer(); |
} |
Member(std::nullptr_t) : m_raw(nullptr) |
{ |
+ checkPointer(); |
} |
Member(T* raw) : m_raw(raw) |
@@ -762,6 +782,7 @@ public: |
Member& operator=(std::nullptr_t) |
{ |
m_raw = nullptr; |
+ checkPointer(); |
return *this; |
} |
@@ -771,17 +792,38 @@ public: |
checkPointer(); |
} |
- T* get() const { return m_raw; } |
+ T* get() const |
+ { |
+#if ENABLE(ASSERT) |
+ if (m_raw && m_gcGeneration) { |
+ ASSERT(m_gcGeneration == GCMixinTrait<T>::heapObjectHeader(m_raw)->gcGeneration()); |
+ } |
+#endif |
+ return m_raw; |
+ } |
- void clear() { m_raw = nullptr; } |
+ // This method is an accessor without any security checks, and it is |
+ // expected to be used under some limited condition. |
+ // So do NOT use it, if you do not know what it means. |
+ T* unsafeGet() const |
+ { |
+ return m_raw; |
+ } |
+ void clear() |
+ { |
+ m_raw = nullptr; |
+ checkPointer(); |
+ } |
protected: |
void checkPointer() |
{ |
#if ENABLE(ASSERT) |
- if (!m_raw) |
+ if (!m_raw) { |
+ m_gcGeneration = 0; |
return; |
+ } |
// HashTable can store a special value (which is not aligned to the |
// allocation granularity) to Member<> to represent a deleted entry. |
// Thus we treat a pointer that is not aligned to the granularity |
@@ -799,16 +841,22 @@ protected: |
// but we cannot call it here because it requires to include T.h. |
// So we currently only try to implement the check for (a), but do |
// not insist that T's definition is in scope. |
- if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) |
- ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); |
+ if (IsFullyDefined<T>::value) { |
+ m_gcGeneration = GCMixinTrait<T>::heapObjectHeader(m_raw)->gcGeneration(); |
+ } else { |
+ m_gcGeneration = 0; |
+ } |
#endif |
} |
T* m_raw; |
+#if ENABLE(ASSERT) |
+ uint16_t m_gcGeneration; |
+#endif |
+ |
template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStrongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; |
friend class Visitor; |
- |
}; |
// WeakMember is similar to Member in that it is used to point to other oilpan |
@@ -869,6 +917,7 @@ public: |
WeakMember& operator=(std::nullptr_t) |
{ |
this->m_raw = nullptr; |
+ this->checkPointer(); |
return *this; |
} |
@@ -941,13 +990,14 @@ public: |
UntracedMember& operator=(std::nullptr_t) |
{ |
this->m_raw = nullptr; |
+ this->checkPointer(); |
return *this; |
} |
}; |
// Comparison operators between (Weak)Members, Persistents, and UntracedMembers. |
-template<typename T, typename U> inline bool operator==(const Member<T>& a, const Member<U>& b) { return a.get() == b.get(); } |
-template<typename T, typename U> inline bool operator!=(const Member<T>& a, const Member<U>& b) { return a.get() != b.get(); } |
+template<typename T, typename U> inline bool operator==(const Member<T>& a, const Member<U>& b) { return a.unsafeGet() == b.unsafeGet(); } |
+template<typename T, typename U> inline bool operator!=(const Member<T>& a, const Member<U>& b) { return a.unsafeGet() != b.unsafeGet(); } |
template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); } |
template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); } |
@@ -1414,11 +1464,9 @@ template<typename T> struct PtrHash<blink::Member<T>> : PtrHash<T*> { |
static bool equal(const U& a, const V& b) { return a == b; } |
}; |
-template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Member<T>> { |
-}; |
+template<typename T> struct PtrHash<blink::WeakMember<T>> : PtrHash<blink::Member<T>> { }; |
-template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::Member<T>> { |
-}; |
+template<typename T> struct PtrHash<blink::UntracedMember<T>> : PtrHash<blink::Member<T>> { }; |
// PtrHash is the default hash for hash tables with members. |
template<typename T> struct DefaultHash<blink::Member<T>> { |