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

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: short copyright header 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 WTF_MAKE_NONCOPYABLE(WrapperPersistentNode);
160 public:
161 bool isAlive() { return m_regionOffset & wrapperPersistentLiveBitMask; }
162
163 WrapperPersistentRegion* region()
164 {
165 return reinterpret_cast<WrapperPersistentRegion*>(
166 reinterpret_cast<Address>(this) - (m_regionOffset & wrapperPersisten tOffsetMask));
167 }
168
169 virtual ~WrapperPersistentNode()
170 {
171 m_regionOffset &= ~wrapperPersistentLiveBitMask;
172 }
173
174 virtual void trace(Visitor* visitor) { }
175
176 protected:
177 WrapperPersistentNode() : m_raw(0), m_regionOffset(0) { }
178
179 explicit WrapperPersistentNode(void* raw)
180 {
181 // When the constructor is called the slot should have been taken (takeS lot)
182 // as part of allocating the memory (via operator new). Hence the m_raw
183 // pointer should be 0.
184 ASSERT(!m_raw);
185 m_raw = raw;
186 // The m_regionOffset should always be set as an offset to the containin g
187 // region. However it should not have the live bit set when the construc tor
188 // is called.
189 ASSERT(m_regionOffset && !isAlive());
190 m_regionOffset |= wrapperPersistentLiveBitMask;
haraken 2014/09/02 13:00:37 m_regionOffset = wrapperPersistentLiveBitMask; ?
wibling-chromium 2014/09/02 13:55:33 No, since the offset to the base is already in the
191 }
192
193 private:
194 void initSlot(size_t regionOffset, WrapperPersistentNode* nextFree)
195 {
196 ASSERT(!m_raw);
197 ASSERT(!m_regionOffset);
198 ASSERT(!(regionOffset & ~wrapperPersistentOffsetMask));
199 m_raw = nextFree;
200 m_regionOffset = regionOffset;
201 }
202
203 WrapperPersistentNode* takeSlot()
204 {
205 // The slot should not be alive at the point where it is allocated.
206 ASSERT(!isAlive());
207 WrapperPersistentNode* nextFree = reinterpret_cast<WrapperPersistentNode *>(m_raw);
208 m_raw = 0;
209 return nextFree;
210 }
211
212 WrapperPersistentNode* freeSlot(WrapperPersistentNode* nextFree)
213 {
214 // When the slot is freed the destructor should already have cleared the live bit.
215 ASSERT(!isAlive());
216 m_raw = nextFree;
217 return this;
218 }
219
220 protected:
221 // m_raw is used both to point to the object when the WrapperPersistentNode is used/alive
222 // and to point to the next free wrapperPersistentNode in the region when th e node is
223 // unused/dead.
224 void* m_raw;
225
226 // The m_regionOffset field is an offset from this node to the base of the c ontaining
227 // WrapperPersistentRegion.
228 size_t m_regionOffset;
229
230 friend class WrapperPersistentRegion;
231 };
232
233 template<typename T>
234 class WrapperPersistent FINAL : public WrapperPersistentNode {
235 public:
236 WrapperPersistent() : WrapperPersistentNode(0) { }
237 WrapperPersistent(std::nullptr_t) : WrapperPersistentNode(0) { }
238 WrapperPersistent(T* raw) : WrapperPersistentNode(raw) { }
239 WrapperPersistent(T& raw) : WrapperPersistentNode(&raw) { }
240
241 void* operator new(size_t);
242 void operator delete(void*);
243
244 virtual void trace(Visitor* visitor) { visitor->mark(static_cast<T*>(m_raw)) ; }
245 };
246
247 class WrapperPersistentRegion {
248 WTF_MAKE_NONCOPYABLE(WrapperPersistentRegion);
249 public:
250 WrapperPersistentRegion()
251 {
252 WrapperPersistentNode* nextFree = 0;
253 for (int i = wrapperPersistentsPerRegion - 1; i >= 0; --i) {
254 size_t regionOffset = reinterpret_cast<Address>(&m_entries[i]) - rei nterpret_cast<Address>(this);
255 // Setup the free slot with an offset to the containing region's bas e and a pointer to the next
256 // free slot in the region.
257 m_entries[i].initSlot(regionOffset, nextFree);
258 nextFree = &m_entries[i];
259 }
260 m_prev = 0;
261 m_next = 0;
262 m_freeHead = nextFree;
263 m_count = 0;
264 }
265
266 void* allocate()
267 {
268 if (!m_freeHead)
269 return 0;
270 // We have a free persistent slot in this region.
271 WrapperPersistentNode* freeSlot = m_freeHead;
272 // Take the slot and advance m_freeHead to the next free slot.
273 m_freeHead = freeSlot->takeSlot();
274 m_count++;
275 return reinterpret_cast<void*>(freeSlot);
276 }
277
278 void free(WrapperPersistentNode* object)
279 {
280 ASSERT(object);
281 ASSERT(!object->isAlive());
282 m_freeHead = object->freeSlot(m_freeHead);
283 m_count--;
284 if (!m_count)
285 ThreadState::current()->removeWrapperPersistentRegion(this);
286 }
287
288 bool removeIfNotLast(WrapperPersistentRegion** headPtr);
289 static void insertHead(WrapperPersistentRegion** headPtr, WrapperPersistentR egion* newHead);
290 static WrapperPersistentRegion* removeHead(WrapperPersistentRegion** headPtr );
291 static void* outOfLineAllocate(ThreadState*, WrapperPersistentRegion*);
292 static void trace(WrapperPersistentRegion* head, Visitor* visitor)
293 {
294 for (WrapperPersistentRegion* current = head; current; current = current ->m_next)
295 current->traceRegion(visitor);
296 }
297
298 private:
299 void traceRegion(Visitor* visitor)
300 {
301 size_t live = 0;
302 for (int i = 0; i < wrapperPersistentsPerRegion && live < m_count; ++i) {
303 if (m_entries[i].isAlive()) {
304 m_entries[i].trace(visitor);
305 live++;
306 }
307 }
308 }
309
310 WrapperPersistentRegion* m_prev;
311 WrapperPersistentRegion* m_next;
312 WrapperPersistentNode* m_freeHead;
313 size_t m_count;
314 WrapperPersistentNode m_entries[wrapperPersistentsPerRegion];
315 };
316
317 template<typename T>
318 void* WrapperPersistent<T>::operator new(size_t size)
haraken 2014/09/02 13:00:37 Drop |size|.
wibling-chromium 2014/09/02 13:55:32 I added an assert(size == sizeof(WrapperPersistent
319 {
320 ThreadState* state = ThreadState::current();
321 WrapperPersistentRegion* region = state->wrapperRoots();
322 ASSERT(region);
323 void* persistent = region->allocate();
324 if (!persistent)
325 return WrapperPersistentRegion::outOfLineAllocate(state, region);
326 return persistent;
327 }
328
329 template<typename T>
330 void WrapperPersistent<T>::operator delete(void* object)
331 {
332 WrapperPersistentNode* persistent = static_cast<WrapperPersistentNode*>(obje ct);
333 persistent->region()->free(persistent);
334 }
335
153 // RootsAccessor for Persistent that provides access to thread-local list 336 // RootsAccessor for Persistent that provides access to thread-local list
154 // of persistent handles. Can only be used to create handles that 337 // of persistent handles. Can only be used to create handles that
155 // are constructed and destructed on the same thread. 338 // are constructed and destructed on the same thread.
156 template<ThreadAffinity Affinity> 339 template<ThreadAffinity Affinity>
157 class ThreadLocalPersistents { 340 class ThreadLocalPersistents {
158 public: 341 public:
159 static PersistentNode* roots() { return state()->roots(); } 342 static PersistentNode* roots() { return state()->roots(); }
160 343
161 // No locking required. Just check that we are at the right thread. 344 // No locking required. Just check that we are at the right thread.
162 class Lock { 345 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> { 1384 struct ParamStorageTraits<T*> : public PointerParamStorageTraits<T*, blink::IsGa rbageCollectedType<T>::value> {
1202 }; 1385 };
1203 1386
1204 template<typename T> 1387 template<typename T>
1205 struct ParamStorageTraits<RawPtr<T> > : public PointerParamStorageTraits<T*, bli nk::IsGarbageCollectedType<T>::value> { 1388 struct ParamStorageTraits<RawPtr<T> > : public PointerParamStorageTraits<T*, bli nk::IsGarbageCollectedType<T>::value> {
1206 }; 1389 };
1207 1390
1208 } // namespace WTF 1391 } // namespace WTF
1209 1392
1210 #endif 1393 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698