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