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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 | 143 |
144 private: | 144 private: |
145 PersistentNode* m_next; | 145 PersistentNode* m_next; |
146 PersistentNode* m_prev; | 146 PersistentNode* m_prev; |
147 | 147 |
148 template<typename RootsAccessor, typename Owner> friend class PersistentBase ; | 148 template<typename RootsAccessor, typename Owner> friend class PersistentBase ; |
149 friend class PersistentAnchor; | 149 friend class PersistentAnchor; |
150 friend class ThreadState; | 150 friend class ThreadState; |
151 }; | 151 }; |
152 | 152 |
153 | |
154 const int wrapperPersistentsPerRegion = 256; | |
155 const size_t wrapperPersistentOffsetMask = ~static_cast<size_t>(3); | |
156 const size_t wrapperPersistentLiveBitMask = 1; | |
157 | |
158 class WrapperPersistentNode { | |
159 public: | |
160 explicit WrapperPersistentNode(const WrapperPersistentNode& otherref) | |
161 { | |
162 WrapperPersistentNode* other = const_cast<WrapperPersistentNode*>(&other ref); | |
163 m_raw = other->m_raw; | |
164 m_offset = other->m_offset; | |
165 } | |
166 | |
167 bool isAlive() { return m_offset & wrapperPersistentLiveBitMask; } | |
168 | |
169 WrapperPersistentRegion* region() | |
170 { | |
171 return reinterpret_cast<WrapperPersistentRegion*>( | |
172 reinterpret_cast<Address>(this) - (m_offset & wrapperPersistentOffse tMask)); | |
173 } | |
174 | |
175 virtual ~WrapperPersistentNode() | |
176 { | |
177 m_offset &= ~wrapperPersistentLiveBitMask; | |
178 } | |
179 | |
180 virtual void trace(Visitor* visitor) { } | |
haraken
2014/09/02 05:22:05
You won't need this. You can just define non-virtu
wibling-chromium
2014/09/02 11:19:37
I do need this, since I am calling m_entries[i].tr
| |
181 | |
182 protected: | |
183 WrapperPersistentNode() : m_raw(0), m_offset(0) { } | |
184 | |
185 explicit WrapperPersistentNode(void* raw) | |
186 { | |
haraken
2014/09/02 05:22:05
Can we add ASSERT(!m_raw) ?
wibling-chromium
2014/09/02 11:19:37
Done.
| |
187 m_raw = raw; | |
188 m_offset |= wrapperPersistentLiveBitMask; | |
zerny-chromium
2014/09/01 14:13:37
m_offset is uninitialized here. Maybe just m_offse
wibling-chromium
2014/09/02 11:19:37
m_offset has already been initialized here to have
| |
189 } | |
190 | |
191 WrapperPersistentNode(size_t offset, WrapperPersistentNode* nextFree) | |
192 { | |
193 ASSERT(!(offset & ~wrapperPersistentOffsetMask)); | |
194 m_raw = reinterpret_cast<void*>(nextFree); | |
195 m_offset = offset; | |
196 } | |
197 | |
198 protected: | |
199 void* m_raw; | |
Mads Ager (chromium)
2014/09/01 13:52:46
Add a comment that m_raw is used to chain freelist
wibling-chromium
2014/09/02 11:19:38
Done.
| |
200 | |
201 private: | |
202 size_t m_offset; | |
haraken
2014/09/02 05:22:05
m_offset => m_region or m_regionHead
haraken
2014/09/02 05:22:05
Add a comment about the memory structure of m_offs
wibling-chromium
2014/09/02 11:19:37
Changed it to m_regionOffset.
wibling-chromium
2014/09/02 11:19:37
Done.
| |
203 | |
204 friend class WrapperPersistentRegion; | |
205 }; | |
206 | |
207 template<typename T> | |
208 class WrapperPersistent : public WrapperPersistentNode { | |
haraken
2014/09/02 05:22:05
Add FINAL.
wibling-chromium
2014/09/02 11:19:37
Done.
| |
209 public: | |
210 WrapperPersistent() : WrapperPersistentNode(0) { } | |
211 WrapperPersistent(std::nullptr_t) : WrapperPersistentNode(0) { } | |
212 WrapperPersistent(T* raw) : WrapperPersistentNode(raw) { } | |
213 WrapperPersistent(T& raw) : WrapperPersistentNode(&raw) { } | |
214 | |
215 void* operator new(size_t); | |
216 void operator delete(void*); | |
217 | |
218 virtual void trace(Visitor* visitor) { visitor->mark(static_cast<T*>(m_raw)) ; } | |
219 }; | |
220 | |
221 class WrapperPersistentRegion { | |
222 public: | |
223 WrapperPersistentRegion() | |
224 { | |
225 WrapperPersistentNode* nextFree = 0; | |
226 for (int i = wrapperPersistentsPerRegion-1; i >= 0; --i) { | |
Mads Ager (chromium)
2014/09/01 13:52:46
Nit: space around '-'
wibling-chromium
2014/09/02 11:19:37
Done.
| |
227 size_t offset = reinterpret_cast<Address>(&m_entries[i]) - reinterpr et_cast<Address>(this); | |
228 new (&m_entries[i]) WrapperPersistentNode(offset, nextFree); | |
229 nextFree = &m_entries[i]; | |
230 } | |
231 m_prev = 0; | |
232 m_next = 0; | |
233 m_free = nextFree; | |
234 m_count = 0; | |
235 } | |
236 | |
237 void* allocate() | |
Erik Corry
2014/09/01 13:40:41
I think you want this to be inlined, and you expec
wibling-chromium
2014/09/02 11:19:38
Done.
| |
238 { | |
239 if (m_free) { | |
240 // We have a free persistent in this region. | |
241 WrapperPersistentNode* free = m_free; | |
242 m_free = reinterpret_cast<WrapperPersistentNode*>(free->m_raw); | |
Mads Ager (chromium)
2014/09/01 13:52:46
Maybe wrap this in a method: free->nextFree().
Th
wibling-chromium
2014/09/02 11:19:37
I have added a takeSlot and freeSlot method in add
| |
243 free->m_raw = 0; | |
244 m_count++; | |
245 return reinterpret_cast<void*>(free); | |
246 } | |
247 // Otherwise try next region if one exists. | |
248 if (m_next) | |
249 return m_next->allocate(); | |
Mads Ager (chromium)
2014/09/01 13:52:46
Can we use iteration iteration from the outside in
wibling-chromium
2014/09/02 11:19:37
Done.
| |
250 return 0; | |
251 } | |
252 | |
253 void free(WrapperPersistentNode* object) | |
254 { | |
255 ASSERT(object); | |
256 ASSERT(!object->isAlive()); | |
257 object->m_raw = m_free; | |
258 m_free = object; | |
259 m_count--; | |
260 if (!m_count) | |
261 ThreadState::current()->removeWrapperPersistentRegion(this); | |
262 } | |
263 | |
264 void trace(Visitor* visitor) | |
265 { | |
266 size_t live = 0; | |
267 for (int i = 0; i < wrapperPersistentsPerRegion && live < m_count; ++i) { | |
268 if (m_entries[i].isAlive()) { | |
269 m_entries[i].trace(visitor); | |
270 live++; | |
271 } | |
272 } | |
273 if (m_next) | |
274 m_next->trace(visitor); | |
Mads Ager (chromium)
2014/09/01 13:52:46
Can we use iteration from the outside instead of r
wibling-chromium
2014/09/02 11:19:37
Done.
| |
275 } | |
276 | |
277 size_t count() const { return m_count; } | |
278 | |
279 bool removeIfNotLast(WrapperPersistentRegion** headPtr) | |
haraken
2014/09/02 05:22:05
Shall we move not-performance-sensitive methods to
wibling-chromium
2014/09/02 11:19:38
Done.
| |
280 { | |
281 // We are the last region in the list if both the region's m_prev and | |
282 // m_next are 0. | |
283 if (m_prev == 0 && m_next == 0) | |
284 return false; | |
285 if (m_prev) { | |
haraken
2014/09/02 05:22:05
Can we just call removeHead() here?
wibling-chromium
2014/09/02 11:19:37
No, that is always removing the head entry via the
| |
286 m_prev->m_next = m_next; | |
287 } else { | |
288 ASSERT(*headPtr == this); | |
289 *headPtr = m_next; | |
290 } | |
291 if (m_next) | |
292 m_next->m_prev = m_prev; | |
293 m_prev = 0; | |
294 m_next = 0; | |
295 return true; | |
296 } | |
297 | |
298 static void insertHead(WrapperPersistentRegion** headPtr, WrapperPersistentR egion* newHead) | |
299 { | |
300 ASSERT(headPtr); | |
301 WrapperPersistentRegion* oldHead = *headPtr; | |
302 if (oldHead) { | |
303 ASSERT(!oldHead->m_prev); | |
304 oldHead->m_prev = newHead; | |
305 } | |
306 newHead->m_prev = 0; | |
307 newHead->m_next = oldHead; | |
308 *headPtr = newHead; | |
309 } | |
310 | |
311 static WrapperPersistentRegion* removeHead(WrapperPersistentRegion** headPtr ) | |
312 { | |
313 // We only call this if there is at least one element in the list. | |
314 ASSERT(headPtr && *headPtr); | |
315 WrapperPersistentRegion* oldHead = *headPtr; | |
316 ASSERT(!oldHead->m_prev); | |
317 *headPtr = oldHead->m_next; | |
318 oldHead->m_next = 0; | |
319 ASSERT(!(*headPtr) || (*headPtr)->m_prev == oldHead); | |
320 if (*headPtr) | |
321 (*headPtr)->m_prev = 0; | |
322 return oldHead; | |
323 } | |
324 | |
325 private: | |
326 WrapperPersistentRegion* m_prev; | |
327 WrapperPersistentRegion* m_next; | |
haraken
2014/09/02 05:22:05
Shall we override 'operator new=' in a private sec
wibling-chromium
2014/09/02 11:19:37
Are you referring to the assignment operator? If s
| |
328 WrapperPersistentNode* m_free; | |
329 size_t m_count; | |
330 WrapperPersistentNode m_entries[wrapperPersistentsPerRegion]; | |
331 }; | |
332 | |
333 template<typename T> | |
334 void* WrapperPersistent<T>::operator new(size_t size) | |
335 { | |
336 ThreadState* state = ThreadState::current(); | |
337 WrapperPersistentRegion* region = state->wrapperRoots(); | |
338 void* persistent = region->allocate(); | |
339 if (!persistent) { | |
340 region = state->addWrapperPersistentRegion(); | |
341 persistent = region->allocate(); | |
342 } | |
343 ASSERT(persistent); | |
344 return persistent; | |
345 } | |
346 | |
347 template<typename T> | |
348 void WrapperPersistent<T>::operator delete(void* object) | |
349 { | |
350 WrapperPersistentNode* persistent = static_cast<WrapperPersistentNode*>(obje ct); | |
351 persistent->region()->free(persistent); | |
352 } | |
353 | |
153 // RootsAccessor for Persistent that provides access to thread-local list | 354 // RootsAccessor for Persistent that provides access to thread-local list |
154 // of persistent handles. Can only be used to create handles that | 355 // of persistent handles. Can only be used to create handles that |
155 // are constructed and destructed on the same thread. | 356 // are constructed and destructed on the same thread. |
156 template<ThreadAffinity Affinity> | 357 template<ThreadAffinity Affinity> |
157 class ThreadLocalPersistents { | 358 class ThreadLocalPersistents { |
158 public: | 359 public: |
159 static PersistentNode* roots() { return state()->roots(); } | 360 static PersistentNode* roots() { return state()->roots(); } |
160 | 361 |
161 // No locking required. Just check that we are at the right thread. | 362 // No locking required. Just check that we are at the right thread. |
162 class Lock { | 363 class Lock { |
(...skipping 1038 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1201 struct ParamStorageTraits<T*> : public PointerParamStorageTraits<T*, blink::IsGa rbageCollectedType<T>::value> { | 1402 struct ParamStorageTraits<T*> : public PointerParamStorageTraits<T*, blink::IsGa rbageCollectedType<T>::value> { |
1202 }; | 1403 }; |
1203 | 1404 |
1204 template<typename T> | 1405 template<typename T> |
1205 struct ParamStorageTraits<RawPtr<T> > : public PointerParamStorageTraits<T*, bli nk::IsGarbageCollectedType<T>::value> { | 1406 struct ParamStorageTraits<RawPtr<T> > : public PointerParamStorageTraits<T*, bli nk::IsGarbageCollectedType<T>::value> { |
1206 }; | 1407 }; |
1207 | 1408 |
1208 } // namespace WTF | 1409 } // namespace WTF |
1209 | 1410 |
1210 #endif | 1411 #endif |
OLD | NEW |