| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 private: | 80 private: |
| 81 PersistentNode* m_next; | 81 PersistentNode* m_next; |
| 82 PersistentNode* m_prev; | 82 PersistentNode* m_prev; |
| 83 | 83 |
| 84 template<typename RootsAccessor, typename Owner> friend class PersistentBase
; | 84 template<typename RootsAccessor, typename Owner> friend class PersistentBase
; |
| 85 friend class PersistentAnchor; | 85 friend class PersistentAnchor; |
| 86 friend class ThreadState; | 86 friend class ThreadState; |
| 87 }; | 87 }; |
| 88 | 88 |
| 89 | 89 |
| 90 const int wrapperPersistentsPerRegion = 256; | |
| 91 const size_t wrapperPersistentOffsetMask = ~static_cast<size_t>(3); | |
| 92 const size_t wrapperPersistentLiveBitMask = 1; | |
| 93 | |
| 94 class WrapperPersistentNode { | |
| 95 WTF_MAKE_NONCOPYABLE(WrapperPersistentNode); | |
| 96 public: | |
| 97 bool isAlive() { return m_regionOffset & wrapperPersistentLiveBitMask; } | |
| 98 | |
| 99 WrapperPersistentRegion* region() | |
| 100 { | |
| 101 return reinterpret_cast<WrapperPersistentRegion*>( | |
| 102 reinterpret_cast<Address>(this) - (m_regionOffset & wrapperPersisten
tOffsetMask)); | |
| 103 } | |
| 104 | |
| 105 virtual ~WrapperPersistentNode() | |
| 106 { | |
| 107 m_regionOffset &= ~wrapperPersistentLiveBitMask; | |
| 108 } | |
| 109 | |
| 110 virtual void trace(Visitor* visitor) { } | |
| 111 | |
| 112 protected: | |
| 113 WrapperPersistentNode() : m_raw(0), m_regionOffset(0) { } | |
| 114 | |
| 115 explicit WrapperPersistentNode(void* raw) | |
| 116 { | |
| 117 // When the constructor is called the slot should have been taken (takeS
lot) | |
| 118 // as part of allocating the memory (via operator new). Hence the m_raw | |
| 119 // pointer should be 0. | |
| 120 ASSERT(!m_raw); | |
| 121 m_raw = raw; | |
| 122 // The m_regionOffset should always be set as an offset to the containin
g | |
| 123 // region. However it should not have the live bit set when the construc
tor | |
| 124 // is called. | |
| 125 ASSERT(m_regionOffset); | |
| 126 ASSERT(!isAlive()); | |
| 127 m_regionOffset |= wrapperPersistentLiveBitMask; | |
| 128 } | |
| 129 | |
| 130 private: | |
| 131 void initSlot(size_t regionOffset, WrapperPersistentNode* nextFree) | |
| 132 { | |
| 133 ASSERT(!m_raw); | |
| 134 ASSERT(!m_regionOffset); | |
| 135 ASSERT(!(regionOffset & ~wrapperPersistentOffsetMask)); | |
| 136 m_raw = nextFree; | |
| 137 m_regionOffset = regionOffset; | |
| 138 } | |
| 139 | |
| 140 WrapperPersistentNode* takeSlot() | |
| 141 { | |
| 142 // The slot should not be alive at the point where it is allocated. | |
| 143 ASSERT(!isAlive()); | |
| 144 WrapperPersistentNode* nextFree = reinterpret_cast<WrapperPersistentNode
*>(m_raw); | |
| 145 m_raw = 0; | |
| 146 return nextFree; | |
| 147 } | |
| 148 | |
| 149 WrapperPersistentNode* freeSlot(WrapperPersistentNode* nextFree) | |
| 150 { | |
| 151 // When the slot is freed the destructor should already have cleared the
live bit. | |
| 152 ASSERT(!isAlive()); | |
| 153 m_raw = nextFree; | |
| 154 return this; | |
| 155 } | |
| 156 | |
| 157 protected: | |
| 158 // m_raw is used both to point to the object when the WrapperPersistentNode
is used/alive | |
| 159 // and to point to the next free wrapperPersistentNode in the region when th
e node is | |
| 160 // unused/dead. | |
| 161 void* m_raw; | |
| 162 | |
| 163 // The m_regionOffset field is an offset from this node to the base of the c
ontaining | |
| 164 // WrapperPersistentRegion. | |
| 165 size_t m_regionOffset; | |
| 166 | |
| 167 friend class WrapperPersistentRegion; | |
| 168 }; | |
| 169 | |
| 170 template<typename T> | |
| 171 class WrapperPersistent final : public WrapperPersistentNode { | |
| 172 public: | |
| 173 WrapperPersistent() : WrapperPersistentNode(0) { } | |
| 174 WrapperPersistent(std::nullptr_t) : WrapperPersistentNode(0) { } | |
| 175 WrapperPersistent(T* raw) : WrapperPersistentNode(raw) { } | |
| 176 WrapperPersistent(T& raw) : WrapperPersistentNode(&raw) { } | |
| 177 | |
| 178 void* operator new(size_t); | |
| 179 void operator delete(void*); | |
| 180 | |
| 181 virtual void trace(Visitor* visitor) | |
| 182 { | |
| 183 ASSERT(isAlive()); | |
| 184 visitor->mark(static_cast<T*>(m_raw)); | |
| 185 } | |
| 186 }; | |
| 187 | |
| 188 class PLATFORM_EXPORT WrapperPersistentRegion { | |
| 189 WTF_MAKE_NONCOPYABLE(WrapperPersistentRegion); | |
| 190 public: | |
| 191 WrapperPersistentRegion() | |
| 192 { | |
| 193 WrapperPersistentNode* nextFree = 0; | |
| 194 for (int i = wrapperPersistentsPerRegion - 1; i >= 0; --i) { | |
| 195 size_t regionOffset = reinterpret_cast<Address>(&m_entries[i]) - rei
nterpret_cast<Address>(this); | |
| 196 // Setup the free slot with an offset to the containing region's bas
e and a pointer to the next | |
| 197 // free slot in the region. | |
| 198 m_entries[i].initSlot(regionOffset, nextFree); | |
| 199 nextFree = &m_entries[i]; | |
| 200 } | |
| 201 m_prev = 0; | |
| 202 m_next = 0; | |
| 203 m_freeHead = nextFree; | |
| 204 m_count = 0; | |
| 205 } | |
| 206 | |
| 207 void* allocate() | |
| 208 { | |
| 209 if (!m_freeHead) { | |
| 210 ASSERT(m_count == wrapperPersistentsPerRegion); | |
| 211 return 0; | |
| 212 } | |
| 213 // We have a free persistent slot in this region. | |
| 214 WrapperPersistentNode* freeSlot = m_freeHead; | |
| 215 // Take the slot and advance m_freeHead to the next free slot. | |
| 216 m_freeHead = freeSlot->takeSlot(); | |
| 217 ASSERT(m_count < wrapperPersistentsPerRegion); | |
| 218 m_count++; | |
| 219 return reinterpret_cast<void*>(freeSlot); | |
| 220 } | |
| 221 | |
| 222 void free(WrapperPersistentNode* object) | |
| 223 { | |
| 224 ASSERT(object); | |
| 225 ASSERT(!object->isAlive()); | |
| 226 m_freeHead = object->freeSlot(m_freeHead); | |
| 227 ASSERT(m_count > 0); | |
| 228 m_count--; | |
| 229 if (!m_count) | |
| 230 ThreadState::current()->freeWrapperPersistentRegion(this); | |
| 231 } | |
| 232 | |
| 233 bool removeIfNotLast(WrapperPersistentRegion** headPtr); | |
| 234 static void insertHead(WrapperPersistentRegion** headPtr, WrapperPersistentR
egion* newHead); | |
| 235 static WrapperPersistentRegion* removeHead(WrapperPersistentRegion** headPtr
); | |
| 236 static void* outOfLineAllocate(ThreadState*, WrapperPersistentRegion*); | |
| 237 static void trace(WrapperPersistentRegion* head, Visitor* visitor) | |
| 238 { | |
| 239 for (WrapperPersistentRegion* current = head; current; current = current
->m_next) | |
| 240 current->traceRegion(visitor); | |
| 241 } | |
| 242 | |
| 243 private: | |
| 244 void traceRegion(Visitor* visitor) | |
| 245 { | |
| 246 size_t live = 0; | |
| 247 | |
| 248 #ifdef NDEBUG | |
| 249 for (int i = 0; i < wrapperPersistentsPerRegion && live < m_count; ++i)
{ | |
| 250 #else | |
| 251 // In DEBUG mode we scan all entries to validate we only have m_count | |
| 252 // live entries. | |
| 253 for (int i = 0; i < wrapperPersistentsPerRegion; ++i) { | |
| 254 #endif | |
| 255 if (m_entries[i].isAlive()) { | |
| 256 m_entries[i].trace(visitor); | |
| 257 live++; | |
| 258 } | |
| 259 } | |
| 260 ASSERT(live == m_count); | |
| 261 } | |
| 262 | |
| 263 WrapperPersistentRegion* m_prev; | |
| 264 WrapperPersistentRegion* m_next; | |
| 265 WrapperPersistentNode* m_freeHead; | |
| 266 size_t m_count; | |
| 267 WrapperPersistentNode m_entries[wrapperPersistentsPerRegion]; | |
| 268 }; | |
| 269 | |
| 270 template<typename T> | |
| 271 void* WrapperPersistent<T>::operator new(size_t size) | |
| 272 { | |
| 273 ASSERT(size == sizeof(WrapperPersistent<T>)); | |
| 274 ThreadState* state = ThreadState::current(); | |
| 275 WrapperPersistentRegion* region = state->wrapperRoots(); | |
| 276 ASSERT(region); | |
| 277 void* persistent = region->allocate(); | |
| 278 if (!persistent) | |
| 279 return WrapperPersistentRegion::outOfLineAllocate(state, region); | |
| 280 return persistent; | |
| 281 } | |
| 282 | |
| 283 template<typename T> | |
| 284 void WrapperPersistent<T>::operator delete(void* object) | |
| 285 { | |
| 286 WrapperPersistentNode* persistent = static_cast<WrapperPersistentNode*>(obje
ct); | |
| 287 persistent->region()->free(persistent); | |
| 288 } | |
| 289 | |
| 290 // RootsAccessor for Persistent that provides access to thread-local list | 90 // RootsAccessor for Persistent that provides access to thread-local list |
| 291 // of persistent handles. Can only be used to create handles that | 91 // of persistent handles. Can only be used to create handles that |
| 292 // are constructed and destructed on the same thread. | 92 // are constructed and destructed on the same thread. |
| 293 template<ThreadAffinity Affinity> | 93 template<ThreadAffinity Affinity> |
| 294 class ThreadLocalPersistents { | 94 class ThreadLocalPersistents { |
| 295 public: | 95 public: |
| 296 static PersistentNode* roots() { return state()->roots(); } | 96 static PersistentNode* roots() { return state()->roots(); } |
| 297 | 97 |
| 298 // No locking required. Just check that we are at the right thread. | 98 // No locking required. Just check that we are at the right thread. |
| 299 class Lock { | 99 class Lock { |
| (...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1336 struct ParamStorageTraits<T*> : public PointerParamStorageTraits<T*, false> { | 1136 struct ParamStorageTraits<T*> : public PointerParamStorageTraits<T*, false> { |
| 1337 }; | 1137 }; |
| 1338 | 1138 |
| 1339 template<typename T> | 1139 template<typename T> |
| 1340 struct ParamStorageTraits<RawPtr<T> > : public PointerParamStorageTraits<T*, fal
se> { | 1140 struct ParamStorageTraits<RawPtr<T> > : public PointerParamStorageTraits<T*, fal
se> { |
| 1341 }; | 1141 }; |
| 1342 | 1142 |
| 1343 } // namespace WTF | 1143 } // namespace WTF |
| 1344 | 1144 |
| 1345 #endif | 1145 #endif |
| OLD | NEW |