source: proiecte/swift/trunk/lib/hoard-371/src/heaplayers/experimental/seg.h @ 176

Last change on this file since 176 was 176, checked in by (none), 14 years ago
  • imported repo from "guagal"
File size: 10.6 KB
Line 
1// -*- C++ -*-
2
3/*
4
5  Heap Layers: An Extensible Memory Allocation Infrastructure
6 
7  Copyright (C) 2000-2003 by Emery Berger
8  http://www.cs.umass.edu/~emery
9  emery@cs.umass.edu
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
25*/
26
27#ifndef _SEG_H_
28#define _SEG_H_
29
30#include <assert.h>
31
32#include "sassert.h"
33#include "reaplet.h"
34
35namespace HL {
36
37template <int ReapletSize,
38          class SizeClassComputer,
39          class TopHeap>
40class Seg : public TopHeap {
41public:
42
43  enum { Alignment = sizeof(double) };
44
45private:
46
47  Seg (void)
48  {
49    sassert <(sizeof(Reaplet<ReapletSize>) == ReapletSize)> verifyReapletSize;
50  }
51 
52  class SanityChecker {
53  public:
54    SanityChecker (Seg * s)
55      : _s (s)
56      {
57        _s->sanityCheck();
58      }
59    ~SanityChecker (void) {
60      _s->sanityCheck();
61    }
62  private:
63    Seg * _s;
64  };
65
66
67#if 1
68  enum { TopAlignment = TopHeap::Alignment };
69
70  class VerifyAlignment :
71    public sassert <TopAlignment % ReapletSize == 0> {};
72#endif
73
74public:
75
76  __forceinline Seg (void) {
77    for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) {
78      available[i] = 0;
79      full[i] = 0;
80    }
81  }
82
83  ~Seg (void) {
84    clear();
85  }
86
87  __forceinline void * malloc (size_t sz) {
88    SanityChecker c (this);
89    assert (sz <= SizeClassComputer::BIG_OBJECT);
90    const int SizeClass = SizeClassComputer::getSizeClass (sz);
91    // Try to use one of our reaplets to satisfy the request.
92    Reaplet<ReapletSize> * const xs = available[SizeClass];
93    if (xs) {
94      //      assert (!xs->isFull());
95      // We've got one. Now try to get some memory from it.
96      void * const ptr = xs->malloc (SizeClassComputer::bins[SizeClass]);
97      //      printf ("allocated: %x\n", ptr);
98      if (ptr) {
99        // Success! We're out of here.
100        return ptr;
101      } else {
102        // It's full.
103        //      printf ("Full - adios.\n");
104        removeFromAvailable (xs, SizeClass);
105      }
106    }
107    //    printf ("slow!\n");
108    // We have to go get more memory.
109    return slowPathGetMoreMemory (sz);
110  }
111
112
113  __forceinline static size_t getSize (void * ptr) {
114    return (enclosingReaplet (ptr))->getSize();
115  }
116
117  __forceinline void free (void * ptr) {
118    SanityChecker c (this);
119    // printf ("seg free: r = %x\n", r);
120    Reaplet<ReapletSize> * r = enclosingReaplet (ptr);
121    //    printf ("freeing %x to %x\n", ptr, r);
122    //    if (sz <= SizeClassComputer::BIG_OBJECT) {
123    // It's a small object. Free it.
124    bool wasFull = r->isFull(); //  || !r->getAmountAllocated()) {
125    r->free (ptr);
126    if (wasFull) {
127      moveFromFullToAvailable (r);
128    }
129  }
130
131  void clear (void) {
132    SanityChecker c (this);
133    for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) {
134      clearOut (full[i]);
135      clearOut (available[i]);
136    }
137  }
138
139private:
140
141  __forceinline void * slowPathGetMoreMemory (const size_t sz) {
142    //    printf ("slowpathgetmorememory\n");
143    SanityChecker c (this);
144    if (sz <= SizeClassComputer::BIG_OBJECT) {
145      const int SizeClass = SizeClassComputer::getSizeClass (sz);
146      do {
147        // printf ("looking for more memory.\n");
148        Reaplet<ReapletSize> * xs = available[SizeClass];
149        // Look for an available reaplet.
150        if (xs != 0) {
151          assert (!xs->isFull());
152          // We've got one. Now try to get some memory from it.
153          void * ptr = xs->malloc (SizeClassComputer::bins[SizeClass]);
154          if (ptr) {
155            // Success!
156            //      printf ("amt free = %d\n", enclosingReaplet(ptr)->getAmountFree());
157            // printf ("success: found more memory.\n");
158            return ptr;
159          } else {
160            //      printf ("Adios!\n");
161            // This reaplet is out of memory.
162            // Remove it from the available list.
163            removeFromAvailable (xs, SizeClass);
164            // Put it on the full list.
165            putOnFullList (xs, SizeClass);
166          }
167        } else {
168          // The current bin is empty - make another reaplet.
169          int r = insertNewReaplet (SizeClass);
170          if (!r) {
171            return 0;
172          }
173        }
174      } while (1);
175    } else {
176      return makeBigObject (sz);
177    }
178  }
179
180  __forceinline void sanityCheck (void) {
181#if !defined(NDEBUG)
182    // FIX ME
183    //#error "whoa dude. slowing things down."
184    Reaplet<ReapletSize> * q;
185    for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) {
186      // Visit the available list.
187      q = available[i];
188      if (q) {
189        assert (q->getPrev() == 0);
190      }
191      while (q) {
192        if (q->isFull()) {
193          // printf ("allocated = %d\n", q->getAmountAllocated());
194        }
195        assert (!q->isFull());
196        q = (Reaplet<ReapletSize> *) q->getNext();
197      }
198      // Now visit the full list.
199      q = full[i];
200      if (q) {
201        assert (q->getPrev() == 0);
202      }
203      while (q) {
204        assert (q->isFull());
205        q = (Reaplet<ReapletSize> *) q->getNext();
206      }
207    }
208#endif
209  }
210
211  __forceinline
212  void putOnFullList (Reaplet<ReapletSize> * xs,
213                      const int SizeClass) {
214    // printf ("putOnFullList %d\n", SizeClass);
215    SanityChecker c (this);
216    //    assert (!xs->isFull());
217    xs->setNext (full[SizeClass]);
218    xs->setPrev (0);
219    if (full[SizeClass]) {
220      full[SizeClass]->setPrev (xs);
221    }
222    full[SizeClass] = xs;
223    //    xs->markFull();
224  }
225
226  __forceinline void clearOut (Reaplet<ReapletSize> *& list) {
227    SanityChecker c (this);
228    Reaplet<ReapletSize> * q;
229    q = list;
230    while (q) {
231      Reaplet<ReapletSize> * c = q;
232      q = (Reaplet<ReapletSize> *) q->getNext();
233      TopHeap::free (c);
234    }
235    list = 0;
236  }
237
238  __forceinline void removeFromFullList (Reaplet<ReapletSize> * r,
239                                         const size_t sz) {
240    //    printf ("removeFromFullList\n");
241    // prev <-> r <-> next =>
242    // prev <-> next
243    SanityChecker c (this);
244    //    assert (r->isFull());
245    // Remove from full list.
246    Reaplet<ReapletSize> * prev, * next;
247    prev = (Reaplet<ReapletSize> *) r->getPrev();
248    next = (Reaplet<ReapletSize> *) r->getNext();
249    assert (prev != r);
250    assert (next != r);
251    if (prev) {
252      prev->setNext (next);
253    }
254    if (next) {
255      next->setPrev (prev);
256    }
257    const int SizeClass = SizeClassComputer::getSizeClass (sz);
258    if (r == full[SizeClass]) {
259      assert (prev == 0);
260      full[SizeClass] = next;
261    }
262    assert (full[SizeClass] != r);
263    // r->setPrev (0);
264    // r->setNext (0);
265    //    r->markNotFull();
266  }
267
268  __forceinline
269  void moveFromFullToAvailable (Reaplet<ReapletSize> * r) {
270    SanityChecker c (this);
271    const size_t sz = r->getSize();
272    removeFromFullList (r, sz);
273    // Put it on the available list.
274    addToAvailableList (r, sz);
275    assert (r->getPrev() == 0);
276  }
277
278  __forceinline
279  void removeAndFreeReaplet (Reaplet<ReapletSize> * r)
280  {
281    SanityChecker c (this);
282    assert (!r->isFull());
283    const size_t sz = r->getSize();
284    Reaplet<ReapletSize> * n
285      = (Reaplet<ReapletSize> *) r->getNext();
286    Reaplet<ReapletSize> * p
287      = (Reaplet<ReapletSize> *) r->getPrev();
288    if (n) {
289      n->setPrev (p);
290    }
291    if (p) {
292      p->setNext (n);
293    }
294    int sizeclass = SizeClassComputer::getSizeClass (sz);
295    if (available[sizeclass] == r) {
296      available[sizeclass] = n;
297    }
298    //r->setPrev ((Reaplet<ReapletSize> *) 1);
299    //r->setNext ((Reaplet<ReapletSize> *) 1);
300    //r->clear();
301    TopHeap::free (r);
302    //  printf ("reset %d\n", sz);
303  }
304
305  __forceinline
306  int insertNewReaplet (int SizeClass)
307  {
308    // printf ("insertNewReaplet\n");
309    SanityChecker c (this);
310    void * m = TopHeap::malloc (ReapletSize);
311    // NOTE: TopHeap *must* add a reaplet prefix.
312    // Ensure m is aligned properly.
313    assert (((size_t) m & (ReapletSize - 1)) == 0);
314    if (m == 0) {
315      // printf ("NO MORE MEMORY!\n");
316      // No more memory.
317      return 0;
318    }
319    // Make a new Reaplet for this size class.
320    size_t ssz = SizeClassComputer::getClassSize (SizeClass);
321   
322    // printf ("new reaplet!: ssz = %d\n", ssz);
323    available[SizeClass] = new (m) Reaplet<ReapletSize> (ssz);
324    available[SizeClass]->clear();
325    return 1;
326  }
327
328protected:
329
330  __forceinline
331  void addToAvailableList (Reaplet<ReapletSize> * r,
332                           size_t sz)
333  {
334    SanityChecker c (this);
335    //    assert (!r->isFull());
336    const int SizeClass = SizeClassComputer::getSizeClass (sz);
337    Reaplet<ReapletSize> * head = available[SizeClass];
338
339    assert (head != r);
340
341    // r
342    // => r <-> head
343   
344    r->setPrev (0);
345    r->setNext (head);
346    if (head) {
347      head->setPrev (r);
348    }
349    available[SizeClass] = r;
350  }
351
352private:
353
354  NO_INLINE void removeFromAvailable (Reaplet<ReapletSize> * xs,
355                                          const int SizeClass) {
356    //    printf ("removefromavailable %d.\n", SizeClass);
357    // The reaplet xs is out of memory.
358    // Remove it from the linked list.
359    // Note that it is the head of the linked list.
360    //  printf ("Removing REAPLET %x\n", xs);
361    assert (xs->isFull());
362    assert (xs->getPrev() == 0);
363    Reaplet<ReapletSize> * n
364      = (Reaplet<ReapletSize> *) xs->getNext();
365    if (n) {
366      // printf ("setprev.\n");
367      n->setPrev (0);
368      assert (!n->isFull());
369    }
370    available[SizeClass] = n;
371    SanityChecker c (this);
372    // xs->setPrev ((Reaplet<ReapletSize> *) 1);
373    // xs->setNext ((Reaplet<ReapletSize> *) 1);
374    assert (n == 0 || (n->getPrev() == 0));
375  }
376
377  __forceinline static Reaplet<ReapletSize> * enclosingReaplet (void * ptr) {
378    // Find the enclosing reaplet for this pointer.
379    Reaplet<ReapletSize> * r
380      = (Reaplet<ReapletSize> *) (((size_t) ptr) & ~(ReapletSize - 1));
381    return r;
382  }
383
384#if 1
385  NO_INLINE
386  void * makeBigObject (size_t sz) {
387    //    printf ("makeBigObject\n");
388    SanityChecker c (this);
389    //    printf ("make big object: %d\n", sz);
390    // Allocate big objects from the top heap. These must be
391    // ReapletSize aligned.
392    assert (sz > SizeClassComputer::BIG_OBJECT);
393    ReapletBase * m
394      = (ReapletBase *) TopHeap::malloc (sz + sizeof(ReapletBase));
395    // printf ("m = %x, size = %d\n", m, ReapletSize);
396    assert (((size_t) m & (ReapletSize - 1)) == 0);
397    // Put a reaplet base object as a header in the beginning. We
398    // need this for size information.
399    if (m == 0) {
400      return 0;
401    }
402    new (m) ReapletBase (sz, (char *) (m + 1)); 
403    return (void *) (m + 1);
404  }
405#endif
406
407  Reaplet<ReapletSize> * available[SizeClassComputer::NUM_BINS];
408  Reaplet<ReapletSize> * full[SizeClassComputer::NUM_BINS];
409};
410
411};
412
413#endif
Note: See TracBrowser for help on using the repository browser.