Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: Source/platform/heap/Handle.h

Issue 525353002: [oilpan]: optimize the way we allocate persistent handles in wrappers. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698