| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2014 Google Inc. All rights reserved. | 2 * Copyright (C) 2014 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 #include "wtf/RawPtr.h" | 43 #include "wtf/RawPtr.h" |
| 44 #include "wtf/RefCounted.h" | 44 #include "wtf/RefCounted.h" |
| 45 #include "wtf/TypeTraits.h" | 45 #include "wtf/TypeTraits.h" |
| 46 | 46 |
| 47 namespace blink { | 47 namespace blink { |
| 48 | 48 |
| 49 template<typename T> class HeapTerminatedArray; | 49 template<typename T> class HeapTerminatedArray; |
| 50 | 50 |
| 51 class PersistentNode { | 51 class PersistentNode { |
| 52 public: | 52 public: |
| 53 explicit PersistentNode(TraceCallback trace) | 53 PersistentNode(void* raw, TraceCallback trace) |
| 54 : m_trace(trace) | 54 : m_raw(raw) |
| 55 , m_trace(trace) |
| 55 { | 56 { |
| 56 } | 57 } |
| 57 | 58 |
| 58 NO_LAZY_SWEEP_SANITIZE_ADDRESS | 59 NO_LAZY_SWEEP_SANITIZE_ADDRESS |
| 59 bool isHeapObjectAlive() { return m_trace; } | 60 bool isHeapObjectAlive() { return m_trace; } |
| 60 | 61 |
| 61 virtual ~PersistentNode() | 62 virtual ~PersistentNode() |
| 62 { | 63 { |
| 63 ASSERT(isHeapObjectAlive()); | 64 ASSERT(isHeapObjectAlive()); |
| 64 m_trace = nullptr; | 65 m_trace = nullptr; |
| 65 } | 66 } |
| 66 | 67 |
| 67 // Ideally the trace method should be virtual and automatically dispatch | 68 // Ideally the trace method should be virtual and automatically dispatch |
| 68 // to the most specific implementation. However having a virtual method | 69 // to the most specific implementation. However having a virtual method |
| 69 // on PersistentNode leads to too eager template instantiation with MSVC | 70 // on PersistentNode leads to too eager template instantiation with MSVC |
| 70 // which leads to include cycles. | 71 // which leads to include cycles. |
| 71 // Instead we call the constructor with a TraceCallback which knows the | 72 // Instead we call the constructor with a TraceCallback which knows the |
| 72 // type of the most specific child and calls trace directly. See | 73 // type of the most specific child and calls trace directly. See |
| 73 // TraceMethodDelegate in Visitor.h for how this is done. | 74 // TraceMethodDelegate in Visitor.h for how this is done. |
| 74 void trace(Visitor* visitor) | 75 void trace(Visitor* visitor) |
| 75 { | 76 { |
| 76 m_trace(visitor, this); | 77 m_trace(visitor, this); |
| 77 } | 78 } |
| 78 | 79 |
| 79 protected: | 80 protected: |
| 81 void* m_raw; |
| 80 TraceCallback m_trace; | 82 TraceCallback m_trace; |
| 81 | 83 |
| 82 private: | 84 private: |
| 83 PersistentNode* m_next; | 85 PersistentNode* m_next; |
| 84 PersistentNode* m_prev; | 86 PersistentNode* m_prev; |
| 85 | 87 |
| 86 template<typename RootsAccessor, typename Owner> friend class PersistentBase
; | 88 template<typename RootsAccessor, typename Owner> friend class PersistentBase
; |
| 87 friend class PersistentAnchor; | 89 friend class PersistentAnchor; |
| 88 friend class ThreadState; | 90 friend class ThreadState; |
| 89 }; | 91 }; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 typename RootsAccessor::Lock lock; | 135 typename RootsAccessor::Lock lock; |
| 134 ASSERT(m_roots == RootsAccessor::roots()); // Check that the thread is u
sing the same roots list. | 136 ASSERT(m_roots == RootsAccessor::roots()); // Check that the thread is u
sing the same roots list. |
| 135 ASSERT(isHeapObjectAlive()); | 137 ASSERT(isHeapObjectAlive()); |
| 136 ASSERT(m_next->isHeapObjectAlive()); | 138 ASSERT(m_next->isHeapObjectAlive()); |
| 137 ASSERT(m_prev->isHeapObjectAlive()); | 139 ASSERT(m_prev->isHeapObjectAlive()); |
| 138 m_next->m_prev = m_prev; | 140 m_next->m_prev = m_prev; |
| 139 m_prev->m_next = m_next; | 141 m_prev->m_next = m_next; |
| 140 } | 142 } |
| 141 | 143 |
| 142 protected: | 144 protected: |
| 143 inline PersistentBase() | 145 inline PersistentBase(void* raw) |
| 144 : PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline) | 146 : PersistentNode(raw, TraceMethodDelegate<Owner, &Owner::trace>::trampol
ine) |
| 145 #if ENABLE(ASSERT) | 147 #if ENABLE(ASSERT) |
| 146 , m_roots(RootsAccessor::roots()) | 148 , m_roots(RootsAccessor::roots()) |
| 147 #endif | 149 #endif |
| 148 { | 150 { |
| 149 // Persistent must belong to a thread that will GC it. | 151 // Persistent must belong to a thread that will GC it. |
| 150 ASSERT(m_roots == GlobalPersistents::roots() || ThreadState::current()); | 152 ASSERT(m_roots == GlobalPersistents::roots() || ThreadState::current()); |
| 151 typename RootsAccessor::Lock lock; | 153 typename RootsAccessor::Lock lock; |
| 152 m_prev = RootsAccessor::roots(); | 154 m_prev = RootsAccessor::roots(); |
| 153 m_next = m_prev->m_next; | 155 m_next = m_prev->m_next; |
| 154 m_prev->m_next = this; | 156 m_prev->m_next = this; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 183 | 185 |
| 184 virtual ~PersistentAnchor() | 186 virtual ~PersistentAnchor() |
| 185 { | 187 { |
| 186 // FIXME: oilpan: Ideally we should have no left-over persistents at thi
s point. However currently there is a | 188 // FIXME: oilpan: Ideally we should have no left-over persistents at thi
s point. However currently there is a |
| 187 // large number of objects leaked when we tear down the main thread. Sin
ce some of these might contain a | 189 // large number of objects leaked when we tear down the main thread. Sin
ce some of these might contain a |
| 188 // persistent or e.g. be RefCountedGarbageCollected we cannot guarantee
there are no remaining Persistents at | 190 // persistent or e.g. be RefCountedGarbageCollected we cannot guarantee
there are no remaining Persistents at |
| 189 // this point. | 191 // this point. |
| 190 } | 192 } |
| 191 | 193 |
| 192 private: | 194 private: |
| 193 PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &P
ersistentAnchor::trace>::trampoline) | 195 PersistentAnchor() : PersistentNode(nullptr, TraceMethodDelegate<PersistentA
nchor, &PersistentAnchor::trace>::trampoline) |
| 194 { | 196 { |
| 195 m_next = this; | 197 m_next = this; |
| 196 m_prev = this; | 198 m_prev = this; |
| 197 } | 199 } |
| 198 | 200 |
| 199 friend class ThreadState; | 201 friend class ThreadState; |
| 200 }; | 202 }; |
| 201 | 203 |
| 202 template<typename T> | 204 template<typename T> |
| 203 class CrossThreadPersistent; | 205 class CrossThreadPersistent; |
| 204 | 206 |
| 205 // Persistent handles are used to store pointers into the | 207 // Persistent handles are used to store pointers into the |
| 206 // managed heap. As long as the Persistent handle is alive | 208 // managed heap. As long as the Persistent handle is alive |
| 207 // the GC will keep the object pointed to alive. Persistent | 209 // the GC will keep the object pointed to alive. Persistent |
| 208 // handles can be stored in objects and they are not scoped. | 210 // handles can be stored in objects and they are not scoped. |
| 209 // Persistent handles must not be used to contain pointers | 211 // Persistent handles must not be used to contain pointers |
| 210 // between objects that are in the managed heap. They are only | 212 // between objects that are in the managed heap. They are only |
| 211 // meant to point to managed heap objects from variables/members | 213 // meant to point to managed heap objects from variables/members |
| 212 // outside the managed heap. | 214 // outside the managed heap. |
| 213 // | 215 // |
| 214 // A Persistent is always a GC root from the point of view of | 216 // A Persistent is always a GC root from the point of view of |
| 215 // the garbage collector. | 217 // the garbage collector. |
| 216 // | 218 // |
| 217 // We have to construct and destruct Persistent in the same thread. | 219 // We have to construct and destruct Persistent in the same thread. |
| 218 template<typename T> | 220 template<typename T> |
| 219 class Persistent : public PersistentBase<ThreadLocalPersistents<ThreadingTrait<T
>::Affinity>, Persistent<T>> { | 221 class Persistent : public PersistentBase<ThreadLocalPersistents<ThreadingTrait<T
>::Affinity>, Persistent<T>> { |
| 220 public: | 222 public: |
| 221 Persistent() : m_raw(nullptr) { } | 223 typedef PersistentBase<ThreadLocalPersistents<ThreadingTrait<T>::Affinity>,
Persistent<T>> ThreadLocalPersistentBase; |
| 222 | 224 |
| 223 Persistent(std::nullptr_t) : m_raw(nullptr) { } | 225 Persistent() : ThreadLocalPersistentBase(nullptr) { } |
| 224 | 226 |
| 225 Persistent(T* raw) : m_raw(raw) | 227 Persistent(std::nullptr_t) : ThreadLocalPersistentBase(nullptr) { } |
| 228 |
| 229 Persistent(T* raw) : ThreadLocalPersistentBase(raw) |
| 226 { | 230 { |
| 227 checkPointer(); | 231 checkPointer(); |
| 228 recordBacktrace(); | 232 recordBacktrace(); |
| 229 } | 233 } |
| 230 | 234 |
| 231 explicit Persistent(T& raw) : m_raw(&raw) | 235 Persistent(T& raw) : ThreadLocalPersistentBase(&raw) |
| 232 { | 236 { |
| 233 checkPointer(); | 237 checkPointer(); |
| 234 recordBacktrace(); | 238 recordBacktrace(); |
| 235 } | 239 } |
| 236 | 240 |
| 237 Persistent(const Persistent& other) : m_raw(other) | 241 Persistent(const Persistent& other) : ThreadLocalPersistentBase(static_cast<
T*>(other.get())) |
| 238 { | 242 { |
| 239 checkPointer(); | 243 checkPointer(); |
| 240 recordBacktrace(); | 244 recordBacktrace(); |
| 241 } | 245 } |
| 242 | 246 |
| 243 template<typename U> | 247 template<typename U> |
| 244 Persistent(const Persistent<U>& other) : m_raw(other) | 248 Persistent(const Persistent<U>& other) : ThreadLocalPersistentBase(static_ca
st<T*>(other.get())) |
| 245 { | 249 { |
| 246 checkPointer(); | 250 checkPointer(); |
| 247 recordBacktrace(); | 251 recordBacktrace(); |
| 248 } | 252 } |
| 249 | 253 |
| 250 template<typename U> | 254 template<typename U> |
| 251 Persistent(const Member<U>& other) : m_raw(other) | 255 Persistent(const Member<U>& other) : ThreadLocalPersistentBase(static_cast<T
*>(other.get())) |
| 252 { | 256 { |
| 253 checkPointer(); | 257 checkPointer(); |
| 254 recordBacktrace(); | 258 recordBacktrace(); |
| 255 } | 259 } |
| 256 | 260 |
| 257 template<typename U> | 261 template<typename U> |
| 258 Persistent(const RawPtr<U>& other) : m_raw(other.get()) | 262 Persistent(const RawPtr<U>& other) : ThreadLocalPersistentBase(static_cast<T
*>(other.get())) |
| 259 { | 263 { |
| 260 checkPointer(); | 264 checkPointer(); |
| 261 recordBacktrace(); | 265 recordBacktrace(); |
| 262 } | 266 } |
| 263 | 267 |
| 264 void clear() { m_raw = nullptr; } | 268 void clear() |
| 269 { |
| 270 this->m_raw = nullptr; |
| 271 } |
| 265 | 272 |
| 266 virtual ~Persistent() | 273 virtual ~Persistent() |
| 267 { | 274 { |
| 268 m_raw = nullptr; | 275 this->m_raw = nullptr; |
| 269 } | 276 } |
| 270 | 277 |
| 271 template<typename VisitorDispatcher> | 278 template<typename VisitorDispatcher> |
| 272 void trace(VisitorDispatcher visitor) | 279 void trace(VisitorDispatcher visitor) |
| 273 { | 280 { |
| 274 static_assert(sizeof(T), "T must be fully defined"); | 281 static_assert(sizeof(T), "T must be fully defined"); |
| 275 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage
collected object"); | 282 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage
collected object"); |
| 276 #if ENABLE(GC_PROFILING) | 283 #if ENABLE(GC_PROFILING) |
| 277 visitor->setHostInfo(this, m_tracingName.isEmpty() ? "Persistent" : m_tr
acingName); | 284 visitor->setHostInfo(this, m_tracingName.isEmpty() ? "Persistent" : m_tr
acingName); |
| 278 #endif | 285 #endif |
| 279 visitor->mark(m_raw); | 286 visitor->mark(get()); |
| 280 } | 287 } |
| 281 | 288 |
| 282 RawPtr<T> release() | 289 RawPtr<T> release() |
| 283 { | 290 { |
| 284 RawPtr<T> result = m_raw; | 291 RawPtr<T> result = get(); |
| 285 m_raw = nullptr; | 292 this->m_raw = nullptr; |
| 286 return result; | 293 return result; |
| 287 } | 294 } |
| 288 | 295 |
| 289 T& operator*() const { return *m_raw; } | 296 T& operator*() const { return *get(); } |
| 290 | 297 |
| 291 bool operator!() const { return !m_raw; } | 298 bool operator!() const { return !get(); } |
| 292 | 299 |
| 293 operator T*() const { return m_raw; } | 300 operator T*() const { return get(); } |
| 294 operator RawPtr<T>() const { return m_raw; } | 301 operator RawPtr<T>() const { return get(); } |
| 295 | 302 |
| 296 T* operator->() const { return *this; } | 303 T* operator->() const { return *this; } |
| 297 | 304 |
| 298 template<typename U> | 305 template<typename U> |
| 299 Persistent& operator=(U* other) | 306 Persistent& operator=(U* other) |
| 300 { | 307 { |
| 301 m_raw = other; | 308 this->m_raw = static_cast<T*>(other); |
| 302 checkPointer(); | 309 checkPointer(); |
| 303 recordBacktrace(); | 310 recordBacktrace(); |
| 304 return *this; | 311 return *this; |
| 305 } | 312 } |
| 306 | 313 |
| 307 Persistent& operator=(std::nullptr_t) | 314 Persistent& operator=(std::nullptr_t) |
| 308 { | 315 { |
| 309 m_raw = nullptr; | 316 this->m_raw = nullptr; |
| 310 return *this; | 317 return *this; |
| 311 } | 318 } |
| 312 | 319 |
| 313 Persistent& operator=(const Persistent& other) | 320 Persistent& operator=(const Persistent& other) |
| 314 { | 321 { |
| 315 m_raw = other; | 322 this->m_raw = static_cast<T*>(other.get()); |
| 316 checkPointer(); | 323 checkPointer(); |
| 317 recordBacktrace(); | 324 recordBacktrace(); |
| 318 return *this; | 325 return *this; |
| 319 } | 326 } |
| 320 | 327 |
| 321 template<typename U> | 328 template<typename U> |
| 322 Persistent& operator=(const Persistent<U>& other) | 329 Persistent& operator=(const Persistent<U>& other) |
| 323 { | 330 { |
| 324 m_raw = other; | 331 this->m_raw = static_cast<T*>(other.get()); |
| 325 checkPointer(); | 332 checkPointer(); |
| 326 recordBacktrace(); | 333 recordBacktrace(); |
| 327 return *this; | 334 return *this; |
| 328 } | 335 } |
| 329 | 336 |
| 330 template<typename U> | 337 template<typename U> |
| 331 Persistent& operator=(const Member<U>& other) | 338 Persistent& operator=(const Member<U>& other) |
| 332 { | 339 { |
| 333 m_raw = other; | 340 this->m_raw = static_cast<T*>(other.get()); |
| 334 checkPointer(); | 341 checkPointer(); |
| 335 recordBacktrace(); | 342 recordBacktrace(); |
| 336 return *this; | 343 return *this; |
| 337 } | 344 } |
| 338 | 345 |
| 339 template<typename U> | 346 template<typename U> |
| 340 Persistent& operator=(const RawPtr<U>& other) | 347 Persistent& operator=(const RawPtr<U>& other) |
| 341 { | 348 { |
| 342 m_raw = other; | 349 this->m_raw = static_cast<T*>(other.get()); |
| 343 checkPointer(); | 350 checkPointer(); |
| 344 recordBacktrace(); | 351 recordBacktrace(); |
| 345 return *this; | 352 return *this; |
| 346 } | 353 } |
| 347 | 354 |
| 348 T* get() const { return m_raw; } | 355 T* get() const { return reinterpret_cast<T*>(this->m_raw); } |
| 349 | 356 |
| 350 private: | 357 private: |
| 351 void checkPointer() | 358 void checkPointer() |
| 352 { | 359 { |
| 353 #if ENABLE(ASSERT) | 360 #if ENABLE(ASSERT) |
| 354 if (!m_raw) | 361 if (!get()) |
| 355 return; | 362 return; |
| 356 | 363 |
| 357 // Heap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable | 364 // Heap::isHeapObjectAlive() checks that the pointer is a traceable |
| 358 // object. In other words, it checks that the pointer is either of: | 365 // object. In other words, it checks that the pointer is either of: |
| 359 // | 366 // |
| 360 // (a) a pointer to the head of an on-heap object. | 367 // (a) a pointer to the head of an on-heap object. |
| 361 // (b) a pointer to the head of an on-heap mixin object. | 368 // (b) a pointer to the head of an on-heap mixin object. |
| 362 // | 369 // |
| 363 // Otherwise, Heap::isHeapObjectAlive will crash when it calls | 370 // Otherwise, Heap::isHeapObjectAlive will crash when it calls |
| 364 // header->checkHeader(). | 371 // header->checkHeader(). |
| 365 Heap::isHeapObjectAlive(m_raw); | 372 Heap::isHeapObjectAlive(get()); |
| 366 #endif | 373 #endif |
| 367 } | 374 } |
| 368 | 375 |
| 369 #if ENABLE(GC_PROFILING) | 376 #if ENABLE(GC_PROFILING) |
| 370 void recordBacktrace() | 377 void recordBacktrace() |
| 371 { | 378 { |
| 372 if (m_raw) | 379 if (get()) |
| 373 m_tracingName = Heap::createBacktraceString(); | 380 m_tracingName = Heap::createBacktraceString(); |
| 374 } | 381 } |
| 375 | 382 |
| 376 String m_tracingName; | 383 String m_tracingName; |
| 377 #else | 384 #else |
| 378 inline void recordBacktrace() const { } | 385 inline void recordBacktrace() const { } |
| 379 #endif | 386 #endif |
| 380 T* m_raw; | |
| 381 }; | 387 }; |
| 382 | 388 |
| 383 // Unlike Persistent, we can destruct a CrossThreadPersistent in a thread | 389 // Unlike Persistent, we can destruct a CrossThreadPersistent in a thread |
| 384 // different from the construction thread. | 390 // different from the construction thread. |
| 385 template<typename T> | 391 template<typename T> |
| 386 class CrossThreadPersistent : public PersistentBase<GlobalPersistents, CrossThre
adPersistent<T>> { | 392 class CrossThreadPersistent : public PersistentBase<GlobalPersistents, CrossThre
adPersistent<T>> { |
| 387 public: | 393 public: |
| 388 CrossThreadPersistent() : m_raw(nullptr) { } | 394 typedef PersistentBase<GlobalPersistents, CrossThreadPersistent<T>> GlobalPe
rsistentBase; |
| 389 | 395 |
| 390 CrossThreadPersistent(std::nullptr_t) : m_raw(nullptr) { } | 396 CrossThreadPersistent() : GlobalPersistentBase(nullptr) { } |
| 391 | 397 |
| 392 CrossThreadPersistent(T* raw) : m_raw(raw) | 398 CrossThreadPersistent(std::nullptr_t) : GlobalPersistentBase(nullptr) { } |
| 399 |
| 400 CrossThreadPersistent(T* raw) : GlobalPersistentBase(raw) |
| 393 { | 401 { |
| 394 checkPointer(); | 402 checkPointer(); |
| 395 recordBacktrace(); | 403 recordBacktrace(); |
| 396 } | 404 } |
| 397 | 405 |
| 398 explicit CrossThreadPersistent(T& raw) : m_raw(&raw) | 406 CrossThreadPersistent(T& raw) : GlobalPersistentBase(&raw) |
| 399 { | 407 { |
| 400 checkPointer(); | 408 checkPointer(); |
| 401 recordBacktrace(); | 409 recordBacktrace(); |
| 402 } | 410 } |
| 403 | 411 |
| 404 CrossThreadPersistent(const CrossThreadPersistent& other) : m_raw(other) | 412 CrossThreadPersistent(const CrossThreadPersistent& other) : GlobalPersistent
Base(static_cast<T*>(other.get())) |
| 405 { | 413 { |
| 406 checkPointer(); | 414 checkPointer(); |
| 407 recordBacktrace(); | 415 recordBacktrace(); |
| 408 } | 416 } |
| 409 | 417 |
| 410 template<typename U> | 418 template<typename U> |
| 411 CrossThreadPersistent(const CrossThreadPersistent<U>& other) : m_raw(other) | 419 CrossThreadPersistent(const CrossThreadPersistent<U>& other) : GlobalPersist
entBase(static_cast<T*>(other.get())) |
| 412 { | 420 { |
| 413 checkPointer(); | 421 checkPointer(); |
| 414 recordBacktrace(); | 422 recordBacktrace(); |
| 415 } | 423 } |
| 416 | 424 |
| 417 template<typename U> | 425 template<typename U> |
| 418 CrossThreadPersistent(const Member<U>& other) : m_raw(other) | 426 CrossThreadPersistent(const Member<U>& other) : GlobalPersistentBase(static_
cast<T*>(other.get())) |
| 419 { | 427 { |
| 420 checkPointer(); | 428 checkPointer(); |
| 421 recordBacktrace(); | 429 recordBacktrace(); |
| 422 } | 430 } |
| 423 | 431 |
| 424 template<typename U> | 432 template<typename U> |
| 425 CrossThreadPersistent(const RawPtr<U>& other) : m_raw(other.get()) | 433 CrossThreadPersistent(const RawPtr<U>& other) : GlobalPersistentBase(static_
cast<T*>(other.get())) |
| 426 { | 434 { |
| 427 checkPointer(); | 435 checkPointer(); |
| 428 recordBacktrace(); | 436 recordBacktrace(); |
| 429 } | 437 } |
| 430 | 438 |
| 431 void clear() { m_raw = nullptr; } | 439 void clear() |
| 440 { |
| 441 this->m_raw = nullptr; |
| 442 } |
| 432 | 443 |
| 433 virtual ~CrossThreadPersistent() | 444 virtual ~CrossThreadPersistent() |
| 434 { | 445 { |
| 435 m_raw = nullptr; | 446 this->m_raw = nullptr; |
| 436 } | 447 } |
| 437 | 448 |
| 438 template<typename VisitorDispatcher> | 449 template<typename VisitorDispatcher> |
| 439 void trace(VisitorDispatcher visitor) | 450 void trace(VisitorDispatcher visitor) |
| 440 { | 451 { |
| 441 static_assert(sizeof(T), "T must be fully defined"); | 452 static_assert(sizeof(T), "T must be fully defined"); |
| 442 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage
collected object"); | 453 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage
collected object"); |
| 443 #if ENABLE(GC_PROFILING) | 454 #if ENABLE(GC_PROFILING) |
| 444 visitor->setHostInfo(this, m_tracingName.isEmpty() ? "CrossThreadPersist
ent" : m_tracingName); | 455 visitor->setHostInfo(this, m_tracingName.isEmpty() ? "CrossThreadPersist
ent" : m_tracingName); |
| 445 #endif | 456 #endif |
| 446 visitor->mark(m_raw); | 457 visitor->mark(get()); |
| 447 } | 458 } |
| 448 | 459 |
| 449 RawPtr<T> release() | 460 RawPtr<T> release() |
| 450 { | 461 { |
| 451 RawPtr<T> result = m_raw; | 462 RawPtr<T> result = get(); |
| 452 m_raw = nullptr; | 463 this->m_raw = nullptr; |
| 453 return result; | 464 return result; |
| 454 } | 465 } |
| 455 | 466 |
| 456 T& operator*() const { return *m_raw; } | 467 T& operator*() const { return *get(); } |
| 457 | 468 |
| 458 bool operator!() const { return !m_raw; } | 469 bool operator!() const { return !get(); } |
| 459 | 470 |
| 460 operator T*() const { return m_raw; } | 471 operator T*() const { return get(); } |
| 461 operator RawPtr<T>() const { return m_raw; } | 472 operator RawPtr<T>() const { return get(); } |
| 462 | 473 |
| 463 T* operator->() const { return *this; } | 474 T* operator->() const { return *this; } |
| 464 | 475 |
| 465 template<typename U> | 476 template<typename U> |
| 466 CrossThreadPersistent& operator=(U* other) | 477 CrossThreadPersistent& operator=(U* other) |
| 467 { | 478 { |
| 468 m_raw = other; | 479 this->m_raw = static_cast<T*>(other); |
| 469 checkPointer(); | 480 checkPointer(); |
| 470 recordBacktrace(); | 481 recordBacktrace(); |
| 471 return *this; | 482 return *this; |
| 472 } | 483 } |
| 473 | 484 |
| 474 CrossThreadPersistent& operator=(std::nullptr_t) | 485 CrossThreadPersistent& operator=(std::nullptr_t) |
| 475 { | 486 { |
| 476 m_raw = nullptr; | 487 this->m_raw = nullptr; |
| 477 return *this; | 488 return *this; |
| 478 } | 489 } |
| 479 | 490 |
| 480 CrossThreadPersistent& operator=(const CrossThreadPersistent& other) | 491 CrossThreadPersistent& operator=(const CrossThreadPersistent& other) |
| 481 { | 492 { |
| 482 m_raw = other; | 493 this->m_raw = static_cast<T*>(other.get()); |
| 483 checkPointer(); | 494 checkPointer(); |
| 484 recordBacktrace(); | 495 recordBacktrace(); |
| 485 return *this; | 496 return *this; |
| 486 } | 497 } |
| 487 | 498 |
| 488 template<typename U> | 499 template<typename U> |
| 489 CrossThreadPersistent& operator=(const CrossThreadPersistent<U>& other) | 500 CrossThreadPersistent& operator=(const CrossThreadPersistent<U>& other) |
| 490 { | 501 { |
| 491 m_raw = other; | 502 this->m_raw = static_cast<T*>(other.get()); |
| 492 checkPointer(); | 503 checkPointer(); |
| 493 recordBacktrace(); | 504 recordBacktrace(); |
| 494 return *this; | 505 return *this; |
| 495 } | 506 } |
| 496 | 507 |
| 497 template<typename U> | 508 template<typename U> |
| 498 CrossThreadPersistent& operator=(const Member<U>& other) | 509 CrossThreadPersistent& operator=(const Member<U>& other) |
| 499 { | 510 { |
| 500 m_raw = other; | 511 this->m_raw = static_cast<T*>(other.get()); |
| 501 checkPointer(); | 512 checkPointer(); |
| 502 recordBacktrace(); | 513 recordBacktrace(); |
| 503 return *this; | 514 return *this; |
| 504 } | 515 } |
| 505 | 516 |
| 506 template<typename U> | 517 template<typename U> |
| 507 CrossThreadPersistent& operator=(const RawPtr<U>& other) | 518 CrossThreadPersistent& operator=(const RawPtr<U>& other) |
| 508 { | 519 { |
| 509 m_raw = other; | 520 this->m_raw = static_cast<T*>(other.get()); |
| 510 checkPointer(); | 521 checkPointer(); |
| 511 recordBacktrace(); | 522 recordBacktrace(); |
| 512 return *this; | 523 return *this; |
| 513 } | 524 } |
| 514 | 525 |
| 515 T* get() const { return m_raw; } | 526 T* get() const { return reinterpret_cast<T*>(this->m_raw); } |
| 516 | 527 |
| 517 private: | 528 private: |
| 518 void checkPointer() | 529 void checkPointer() |
| 519 { | 530 { |
| 520 #if ENABLE(ASSERT) | 531 #if ENABLE(ASSERT) |
| 521 if (!m_raw) | 532 if (!get()) |
| 522 return; | 533 return; |
| 523 // Heap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable | 534 // Heap::isHeapObjectAlive() checks that the pointer is a traceable |
| 524 // object. In other words, it checks that the pointer is either of: | 535 // object. In other words, it checks that the pointer is either of: |
| 525 // | 536 // |
| 526 // (a) a pointer to the head of an on-heap object. | 537 // (a) a pointer to the head of an on-heap object. |
| 527 // (b) a pointer to the head of an on-heap mixin object. | 538 // (b) a pointer to the head of an on-heap mixin object. |
| 528 // | 539 // |
| 529 // Otherwise, Heap::isHeapObjectAlive will crash when it calls | 540 // Otherwise, Heap::isHeapObjectAlive will crash when it calls |
| 530 // header->checkHeader(). | 541 // header->checkHeader(). |
| 531 Heap::isHeapObjectAlive(m_raw); | 542 Heap::isHeapObjectAlive(get()); |
| 532 #endif | 543 #endif |
| 533 } | 544 } |
| 534 | 545 |
| 535 #if ENABLE(GC_PROFILING) | 546 #if ENABLE(GC_PROFILING) |
| 536 void recordBacktrace() | 547 void recordBacktrace() |
| 537 { | 548 { |
| 538 if (m_raw) | 549 if (get()) |
| 539 m_tracingName = Heap::createBacktraceString(); | 550 m_tracingName = Heap::createBacktraceString(); |
| 540 } | 551 } |
| 541 | 552 |
| 542 String m_tracingName; | 553 String m_tracingName; |
| 543 #else | 554 #else |
| 544 inline void recordBacktrace() const { } | 555 inline void recordBacktrace() const { } |
| 545 #endif | 556 #endif |
| 546 T* m_raw; | |
| 547 }; | 557 }; |
| 548 | 558 |
| 549 // FIXME: derive affinity based on the collection. | 559 // FIXME: derive affinity based on the collection. |
| 550 template<typename Collection, ThreadAffinity Affinity = AnyThread> | 560 template<typename Collection, ThreadAffinity Affinity = AnyThread> |
| 551 class PersistentHeapCollectionBase | 561 class PersistentHeapCollectionBase |
| 552 : public Collection | 562 : public Collection |
| 553 , public PersistentBase<ThreadLocalPersistents<Affinity>, PersistentHeapColl
ectionBase<Collection, Affinity>> { | 563 , public PersistentBase<ThreadLocalPersistents<Affinity>, PersistentHeapColl
ectionBase<Collection, Affinity>> { |
| 554 // We overload the various new and delete operators with using the WTF Defau
ltAllocator to ensure persistent | 564 // We overload the various new and delete operators with using the WTF Defau
ltAllocator to ensure persistent |
| 555 // heap collections are always allocated off-heap. This allows persistent co
llections to be used in | 565 // heap collections are always allocated off-heap. This allows persistent co
llections to be used in |
| 556 // DEFINE_STATIC_LOCAL et. al. | 566 // DEFINE_STATIC_LOCAL et. al. |
| 557 WTF_USE_ALLOCATOR(PersistentHeapCollectionBase, WTF::DefaultAllocator); | 567 WTF_USE_ALLOCATOR(PersistentHeapCollectionBase, WTF::DefaultAllocator); |
| 558 public: | 568 public: |
| 559 PersistentHeapCollectionBase() { } | 569 typedef PersistentBase<ThreadLocalPersistents<Affinity>, PersistentHeapColle
ctionBase<Collection, Affinity>> CollectionPersistentBase; |
| 560 | 570 |
| 561 PersistentHeapCollectionBase(const PersistentHeapCollectionBase& other) : Co
llection(other) { } | 571 PersistentHeapCollectionBase() : CollectionPersistentBase(this) { } |
| 572 |
| 573 PersistentHeapCollectionBase(const PersistentHeapCollectionBase& other) : Co
llection(other), CollectionPersistentBase(this) { } |
| 562 | 574 |
| 563 template<typename OtherCollection> | 575 template<typename OtherCollection> |
| 564 PersistentHeapCollectionBase(const OtherCollection& other) : Collection(othe
r) { } | 576 PersistentHeapCollectionBase(const OtherCollection& other) : Collection(othe
r), CollectionPersistentBase(this) { } |
| 565 | 577 |
| 566 template<typename VisitorDispatcher> | 578 template<typename VisitorDispatcher> |
| 567 void trace(VisitorDispatcher visitor) | 579 void trace(VisitorDispatcher visitor) |
| 568 { | 580 { |
| 569 static_assert(sizeof(Collection), "Collection must be fully defined"); | 581 static_assert(sizeof(Collection), "Collection must be fully defined"); |
| 570 #if ENABLE(GC_PROFILING) | 582 #if ENABLE(GC_PROFILING) |
| 571 visitor->setHostInfo(this, "PersistentHeapCollectionBase"); | 583 visitor->setHostInfo(this, "PersistentHeapCollectionBase"); |
| 572 #endif | 584 #endif |
| 573 visitor->trace(*static_cast<Collection*>(this)); | 585 visitor->trace(*static_cast<Collection*>(this)); |
| 574 } | 586 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 | 653 |
| 642 Member(std::nullptr_t) : m_raw(nullptr) | 654 Member(std::nullptr_t) : m_raw(nullptr) |
| 643 { | 655 { |
| 644 } | 656 } |
| 645 | 657 |
| 646 Member(T* raw) : m_raw(raw) | 658 Member(T* raw) : m_raw(raw) |
| 647 { | 659 { |
| 648 checkPointer(); | 660 checkPointer(); |
| 649 } | 661 } |
| 650 | 662 |
| 651 explicit Member(T& raw) : m_raw(&raw) | 663 Member(T& raw) : m_raw(&raw) |
| 652 { | 664 { |
| 653 checkPointer(); | 665 checkPointer(); |
| 654 } | 666 } |
| 655 | 667 |
| 656 template<typename U> | 668 template<typename U> |
| 657 Member(const RawPtr<U>& other) : m_raw(other.get()) | 669 Member(const RawPtr<U>& other) : m_raw(other.get()) |
| 658 { | 670 { |
| 659 checkPointer(); | 671 checkPointer(); |
| 660 } | 672 } |
| 661 | 673 |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 struct ParamStorageTraits<RawPtr<T>> : public PointerParamStorageTraits<T*, blin
k::IsGarbageCollectedType<T>::value> { | 1271 struct ParamStorageTraits<RawPtr<T>> : public PointerParamStorageTraits<T*, blin
k::IsGarbageCollectedType<T>::value> { |
| 1260 static_assert(sizeof(T), "T must be fully defined"); | 1272 static_assert(sizeof(T), "T must be fully defined"); |
| 1261 }; | 1273 }; |
| 1262 | 1274 |
| 1263 template<typename T> | 1275 template<typename T> |
| 1264 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; | 1276 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; |
| 1265 | 1277 |
| 1266 } // namespace WTF | 1278 } // namespace WTF |
| 1267 | 1279 |
| 1268 #endif | 1280 #endif |
| OLD | NEW |