MemorySegment.hpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel RexxMemorysegment.hpp */
40 /* */
41 /* Primitive MemorySegment class definitions */
42 /* */
43 /******************************************************************************/
44 
45 #ifndef Included_MemorySegment
46 #define Included_MemorySegment
47 
48 #include "stddef.h"
49 #include "DeadObject.hpp"
50 #include "Interpreter.hpp"
51 
52 #define MemorySegmentOverhead (sizeof(MemorySegmentHeader))
53 #define MemorySegmentPoolOverhead (sizeof(MemorySegmentPoolHeader))
54 
55 #ifdef __REXX64__
56 // default size for a segment allocation, we go larger on 64-bit
57 #define SegmentSize (256*1024*2)
58 /* our threshold for moving to a larger block allocation scheme */
59 #define LargeBlockThreshold 8192
60 #else
61 /* default size for a segment allocation */
62 #define SegmentSize (256*1024)
63 /* our threshold for moving to a larger block allocation scheme */
64 #define LargeBlockThreshold 4096
65 #endif
66 /* Minimum size segment we'll allow */
67 #define MinimumSegmentSize (SegmentSize/2)
68 /* amount of usable space in a minimum sized segment */
69 #define MinimumSegmentDeadSpace (MinimumSegmentSize - MemorySegmentOverhead)
70 /* default size for a larger segment allocation */
71 #define LargeSegmentSize (SegmentSize * 4)
72 /* allocation available in a default segment */
73 #define SegmentDeadSpace (SegmentSize - MemorySegmentOverhead)
74 /* allocation request for the recovery segment */
75 #define RecoverSegmentSize ((SegmentSize/2) - MemorySegmentOverhead)
76 /* space available in a larger allocation. */
77 #define LargeSegmentDeadSpace (LargeSegmentSize - MemorySegmentOverhead)
78 
79 #define InitialNormalSegmentSpace ((LargeSegmentSize * 8) - MemorySegmentOverhead)
80 
81 #define LargestNormalSegmentSize (LargeObjectMinSize - (1024 * 1024) - MemorySegmentOverhead)
82 
83 
84 /* Our threshold for deciding we're thrashing the garbage */
85 /* collector. We'll always just extend memory if we're below this */
86 /* request threshold. */
87 #define MemoryThrashingThreshold 4
88 
89 /* map an object length to an allocation deadpool. NOTE: this */
90 /* assumes the length has already been rounded to ObjectGrain! */
91 #define LengthToDeadPool(l) ((l)/ObjectGrain)
92 
93 /* map a dead pool index to the size of blocks held in the pool */
94 #define DeadPoolToLength(d) ((d)*ObjectGrain)
95 /* index of first dead free chain. We start with the previous */
96 /* chain, as older tokenized images can contain objects smaller */
97 /* than our minimum. If these are garbage collected individually, */
98 /* we need a place to put them. */
99 #define FirstDeadPool (LengthToDeadPool(MinimumObjectSize) - 1)
100 /* The largest size element we'll keep in a subpool */
101 #define LargestSubpool 512
102 /* The index of the last subpool dead chain */
103 #define LastDeadPool LengthToDeadPool(LargestSubpool)
104 /* number of free chains (we index zero based, so we need to */
105 /* allocate one additional pool) */
106 #define DeadPools LastDeadPool + 1
107 
108 /* the threshold to trigger expansion of the normal segment set. */
109 #define NormalMemoryExpansionThreshold .30
110 /* The point where we consider releasing segments */
111 #define NormalMemoryContractionThreshold .70
112 
113 /* the sanity check point where we don't force automatic expansion */
114 /* of the normal heap */
115 #define MaxDeadObjectSpace 1000000
116 
117 /* This rounds to segment sized chunks, not taking the overhead into account. */
118 inline size_t roundSegmentBoundary(size_t n) { return RXROUNDUP(n, SegmentSize); }
119 
120 
121 class RexxMemory;
122 
123 /* A segment of heap memory. A MemorySegment will be associated */
124 /* with a particular MemorySegmentSet, which implements the */
125 /* suballocation rules. */
127  friend class MemorySegmentSet;
128  friend class NormalSegmentSet;
129  friend class LargeSegmentSet;
130  friend class OldSegmentSet;
131  friend class RexxMemory;
132 
133  protected:
134  size_t segmentSize; /* size of the segment */
135  size_t liveObjects; /* number of live objects in segment */
136  MemorySegment *next; /* next segment in the chain */
137  MemorySegment *previous; /* previous segment in the chain */
138 };
139 
140 /* A segment of heap memory. A MemorySegment will be associated */
141 /* with a particular MemorySegmentSet, which implements the */
142 /* suballocation rules. */
144  friend class MemorySegmentSet;
145  friend class NormalSegmentSet;
146  friend class LargeSegmentSet;
147  friend class OldSegmentSet;
148  friend class RexxMemory;
149 
150  public:
151  inline void *operator new(size_t size, void *segment) { return segment; }
152  inline void operator delete(void *) { }
153  inline void operator delete(void *, void *) { }
154 
155  inline MemorySegment(size_t segSize) {
156  segmentSize = segSize - sizeof(MemorySegmentHeader);
157  }
158  /* Following is a static constructor, called during RexxMemory */
159  /* initialization */
160  inline MemorySegment() {
161  segmentSize = 0;
162  /* Chain this segment to itself. */
163  next = this;
164  previous = this;
165  }
166 
168  newSegment->next = this->next;
169  newSegment->previous = this;
170  this->next->previous = newSegment;
171  this->next = newSegment;
172  };
173 
175  newSegment->next = this;
176  newSegment->previous = this->previous;
177  this->previous->next = newSegment;
178  this->previous = newSegment;
179  };
180 
181  inline void remove() {
182  this->next->previous = this->previous;
183  this->previous->next = this->next;
184  }
185 
186  inline void removeAll() {
187  firstObject()->remove();
188  remove();
189  }
190 
191  inline bool isInSegment(RexxObject * object) {
192  return (((char *)object >= segmentStart) && ((char *)object <= segmentStart + segmentSize));
193  }
194 
195  inline DeadObject *createDeadObject() { return new ((void *)segmentStart) DeadObject(segmentSize); }
196 
198  inline void combine(MemorySegment *nextSegment) { segmentSize += nextSegment->segmentSize + MemorySegmentOverhead; }
199  inline void shrink(size_t delta) { segmentSize -= delta; }
200  inline bool isAdjacentTo(MemorySegment *seg) { return end() == (char *)seg; }
201  inline bool isLastBlock(char *addr, size_t length) { return (addr + length) == end(); }
202  inline bool isFirstBlock(char *addr) { return addr == start(); }
203 
204  inline size_t size() { return segmentSize; }
205  inline size_t realSize() { return segmentSize + MemorySegmentOverhead; }
206  inline char *start() { return segmentStart; }
207  inline char *end() { return segmentStart + segmentSize; }
208  inline bool isReal() { return segmentSize != 0; }
209  inline bool isEmpty() { return liveObjects == 0; }
210  void dump(const char *owner, size_t counter, FILE *keyfile, FILE *dumpfile);
213  void gatherObjectStats(MemoryStats *memStats, SegmentStats *stats);
214  void markAllObjects();
215 
216  public:
217  char segmentStart[8]; /* start of the object data */
218 };
219 
220 
221 
222 
223 /* A set of memory segments. This manages the access to a pool of */
224 /* memory segments allocated for different uses by RexxMemory. */
225 /* This is a subclass of MemorySegment because the MemorySegmentSet */
226 /* object is also the anchor element for the segment chaining. */
228  friend class RexxMemory;
229 
230  public:
232  /* the memory segment mimic for anchoring the pool */
233  MemorySegmentSet(RexxMemory *memObject, SegmentSetID id, const char *setName) {
234  /* Chain this segment to itself. */
235  owner = id;
236  count = 0;
237  /* keep the link back to the memory object that provides */
238  /* us services. */
239  this->memory = memObject;
240  this->name = setName;
241  }
242  /* the default constructor */
244  /* Chain this segment to itself. */
246  count = 0;
247  /* The link to the memory object will need to be established later */
248  memory = NULL;
249  }
250 
251  virtual ~MemorySegmentSet() { ; }
252  inline void *operator new(size_t size, void *segment) { return segment; }
253  inline void operator delete(void * size) { }
254  inline void operator delete(void * size, void *segment) { }
255 
256  /* Following is a static constructor, called during */
257  /* RexxMemeory initialization */
258 
259  inline void removeSegment(MemorySegment *segment) {
260  /* remove both the segment, and any blocks on the dead */
261  /* chains. */
262  segment->remove();
263  count--;
264  }
265 
266  inline void removeSegmentAndStorage(MemorySegment *segment) {
267  /* remove both the segment, and any blocks on the dead */
268  /* chains. */
269  segment->removeAll();
270  count--;
271  }
272 
273  inline void add(MemorySegment *segment) {
274  anchor.insertBefore(segment);
275  count++;
276  }
277 
278  inline MemorySegment *first() {
279  if (anchor.next->isReal()) {
280  return anchor.next;
281  }
282  else {
283  return NULL;
284  }
285  }
286 
287  inline MemorySegment *next(MemorySegment *segment) {
288  if (segment->next->isReal()) {
289  return segment->next;
290  }
291  else {
292  return NULL;
293  }
294  }
295 
296  inline bool isInSegmentSet(RexxObject *object) {
297  MemorySegment *segment = first();
298  while (segment != NULL) {
299  if (segment->isInSegment(object)) {
300  return true;
301  }
302  segment = next(segment);
303  }
304  return false;
305  }
306 
307 
308  void dumpSegments(FILE *keyfile, FILE *dumpfile);
309  void addSegment(MemorySegment *segment, bool createDeadObject = 1);
310  void sweep();
311  inline bool is(SegmentSetID id) { return owner == id; }
312  void gatherStats(MemoryStats *memStats, SegmentStats *stats);
313 
314 
315  virtual void dumpMemoryProfile(FILE *outfile);
316  virtual DeadObject *donateObject(size_t allocationLength);
317  virtual MemorySegment *donateSegment(size_t allocationLength);
318 
319  protected:
320 
321  virtual void collectEmptySegments();
322  virtual void addDeadObject(DeadObject *object);
323  virtual void addDeadObject(char *object, size_t length);
324  RexxObject *splitDeadObject(DeadObject *object, size_t allocationLength, size_t splitMinimum);
325  void insertSegment(MemorySegment *segment);
326  MemorySegment *findEmptySegment(size_t allocationLength);
327  MemorySegment *splitSegment(size_t allocationLength);
328  void mergeSegments(size_t allocationLength);
330  virtual size_t suggestMemoryExpansion();
331  virtual size_t suggestMemoryContraction();
332  virtual void prepareForSweep();
333  virtual void completeSweepOperation();
336  void adjustMemorySize();
337  void releaseEmptySegments(size_t releaseSize);
338  void releaseSegment(MemorySegment *segment);
339  bool newSegment(size_t requestLength, size_t minimumLength);
340 
341  virtual MemorySegment *allocateSegment(size_t requestLength, size_t minimumLength);
342  inline float freeMemoryPercentage() {return (float)deadObjectBytes/(float)(deadObjectBytes + liveObjectBytes); }
343  inline size_t totalFreeMemory() { return liveObjectBytes + deadObjectBytes; }
344  /* This rounds a size into an even segment multiple, taking the */
345  /* segment overhead into account. */
346  inline size_t calculateSegmentAllocation(size_t n) {
347  size_t size = roundSegmentBoundary(n) - MemorySegmentOverhead;
348  /* this could be true if our size is larger than can fit into a */
349  /* segment once the overhead is considered. If we can't fit, */
350  /* we go over by a segment. */
351  if (size < n) {
352  size += SegmentSize;
353  }
354  return size;
355  }
356  void addSegments(size_t requiredSpace);
357  MemorySegment *getSegment(size_t requestLength, size_t minimumLength);
358  void activateEmptySegments();
359 
360 #ifndef CHECKOREFS
361  inline void validateObject(size_t bytes) {};
362 #else
363  void validateObject(size_t bytes); // Must be moved to .cpp file because compile error with Interpreter::logicError
364 #endif
365 
366 
367 
368  MemorySegment anchor; /* the anchor for our active segment chain */
369  MemorySegment emptySegments; /* our empty segment chain (used for reserves) */
370  size_t count; /* the number of elements in the pool */
371  size_t liveObjectBytes; /* bytes allocation to live objects */
372  size_t deadObjectBytes; /* bytes consumed by dead objects */
373  SegmentSetID owner; /* the owner of this segment */
374  const char *name; /* character identifier for debugging/profiling */
375  RexxMemory *memory; /* the hosting memory object */
376 };
377 
378 
380 {
381  public:
382 
383  /* the default constructor */
386  virtual ~NormalSegmentSet() { ; }
387  virtual void dumpMemoryProfile(FILE *outfile);
388  inline RexxObject *allocateObject(size_t allocationLength)
389  {
390  DeadObject *newObject;
391  size_t targetPool;
392  size_t realLength;
393 
394  /* Calculate the dead chain. Note that if this is larger than */
395  /* the largest subpool, the for() loop test below will fail, */
396  /* causing this to drop down to the large block allocation */
397  /* logic. This eliminates an additional check against the */
398  /* large size. */
399  targetPool = LengthToDeadPool(allocationLength);
400 
401  if (targetPool < DeadPools) {
402 
403  /* pick up the last successful one */
404  size_t currentDead = lastUsedSubpool[targetPool];
405  /* loop through the small pool chains looking for a block. */
406  /* We only go up to the largest blocks as a last resort to */
407  /* reduce the fragmentation. */
408  while (currentDead < DeadPools) {
409  /* See if the chain has an object. Once we get an */
410  /* object, we return this directly. We accept over */
411  /* allocations when then come from the subpool chain. */
412  /* Since this is such a heavily hit path, we don't want */
413  /* to absorb the overhead of attempting to split the */
414  /* blocks. For the majority of over allocations, we */
415  /* can't split anyway. When we do split, the result is */
416  /* a very small fragment. */
417  newObject = subpools[currentDead].getFirstSingle();
418  if (newObject != OREF_NULL) {
419  /* Record the success. Next time around, */
420  /* allocations will come directly here. */
421  lastUsedSubpool[targetPool] = currentDead;
422  /* we have a block. Now see if we got this from a */
423  /* higher level chain and have enough room to */
424  /* subdivide into a small block. */
425  /* Convert this from a dead object into a real one of the */
426  /* given size. */
427  return (RexxObject *)newObject;
428  }
429 
430  currentDead++;
431 
432  while (currentDead < DeadPools)
433  {
434  if (lastUsedSubpool[currentDead] < DeadPools)
435  {
436  // this pool might be redirected already, so
437  // pick up the index of where it's redirected to.
438  currentDead = lastUsedSubpool[currentDead];
439  lastUsedSubpool[targetPool] = currentDead;
440  break;
441  }
442  currentDead++;
443  }
444  }
445  /* we've gone all the way to the end without finding */
446  /* anything. Cause the next allocation to skip directly to */
447  /* the large chain. */
448  lastUsedSubpool[targetPool] = DeadPools;
449  }
450  /* Nope, go through the LARGEDEAD object looking for the 1st */
451  /* one we can use either our object is too big for all the */
452  /* small chains, or the small chains are depleted.... */
453  /* Go through the LARGEDEAD object looking for the 1st */
454  /* one we can use either our object is too big for all the */
455  /* small chains, or the small chains are depleted.... */
456  newObject = largeDead.findFit(allocationLength, &realLength);
457  if (newObject != NULL) { /* did we find an object? */
458  size_t deadLength = realLength - allocationLength;
459  /* remainder too small or this is a very large request */
460  /* is the remainder two small to reuse? */
461  if (deadLength < MinimumObjectSize) {
462  /* Convert this from a dead object into a real one of the */
463  /* given size. */
464  return (RexxObject *)newObject;
465  }
466  else {
467  /* potentially split this object into a smaller unit so we */
468  /* can reuse the remainder. */
469  return splitNormalDeadObject(newObject, allocationLength, deadLength);
470  }
471  }
472  return OREF_NULL;
473  }
474 
475  RexxObject *handleAllocationFailure(size_t allocationLength);
476  virtual DeadObject *donateObject(size_t allocationLength);
477  void getInitialSet();
478  virtual size_t suggestMemoryExpansion();
479  virtual size_t suggestMemoryContraction();
480 
481  protected:
482  virtual void addDeadObject(DeadObject *object);
483  virtual void addDeadObject(char *object, size_t length);
484  virtual void prepareForSweep();
485  void completeSweepOperation();
486 
487  private:
488 
489  inline size_t mapLengthToDeadPool(size_t length) { return length/ObjectGrain; }
490  RexxObject *findLargeDeadObject(size_t allocationLength);
491  inline size_t recommendedMemorySize() { return (size_t)((float)liveObjectBytes/(1.0 - NormalMemoryExpansionThreshold)); }
492  inline size_t recommendedMaximumMemorySize() { return (size_t)((float)liveObjectBytes/(1.0 - NormalMemoryContractionThreshold)); }
493  void checkObjectOverlap(DeadObject *obj);
494  RexxObject *findObject(size_t allocationLength);
495  inline RexxObject *splitNormalDeadObject(DeadObject *object, size_t allocationLength, size_t deadLength)
496  {
497  /* we need to keep all of these sizes as ObjectGrain multiples, */
498  /* so round it down...the allocation will get all of the extra. */
499  /* deadLength = rounddown(deadLength, ObjectGrain);
500  allocationLength is rounded, deadLength might be
501  an ungrained object size from old tokenized format */
502 
503  /* Yes, so pull new object out of the front of the dead */
504  /* object, adjust the size of the Dead object. We want */
505  /* to use the front rather than the back so that if we */
506  /* hit the need to split a segment because of low memory */
507  /* conditions, we increase the probability that we'll be */
508  /* able to use the end of the segment. */
509  DeadObject *largeObject = (DeadObject *)(((char *)object) + allocationLength);
510  /* if the length is larger than the biggest subpool we */
511  /* maintain, we add this to the large block list. */
512  if (deadLength > LargestSubpool) {
513  /* ideally, we'd like to add this sorted by size, but */
514  /* this is called so frequently, attempting to sort */
515  /* degrades performance by about 10%. */
516  largeDead.add(new (largeObject) DeadObject(deadLength));
517  }
518  else {
519  /* calculate the dead chain */
520  /* and add that to the appropriate chain */
521  size_t deadChain = LengthToDeadPool(deadLength);
522  subpools[deadChain].addSingle(new (largeObject) DeadObject(deadLength));
523  /* we can mark this subpool as having items again */
524  lastUsedSubpool[deadChain] = deadChain;
525  }
526  /* Convert this from a dead object into a real one of the */
527  /* given size. */
528  ((RexxObject *)object)->setObjectSize(allocationLength);
529  return (RexxObject *)object;
530  }
531 
532  DeadObjectPool largeDead; /* the set of large dead objects */
533  DeadObjectPool subpools[DeadPools]; /* our set of allocation subpools */
534  size_t lastUsedSubpool[DeadPools + 1];/* a look-aside index to tell us what pool to use for a given size */
535  MemorySegment *recoverSegment; /* our last-ditch memory segment */
536 };
537 
538 
540 {
541  public:
542 
543  /* the default constructor */
546  virtual ~LargeSegmentSet() { ; }
547  virtual void dumpMemoryProfile(FILE *outfile);
548  RexxObject *handleAllocationFailure(size_t allocationLength);
549  inline RexxObject *allocateObject(size_t allocationLength)
550  {
551  DeadObject *largeObject;
552 
553  /* go through the LARGEDEAD object looking for the 1st one we can */
554  /* use either our object is too big for all the small chains, or */
555  /* the small chain are depleted.... */
556  largeObject = deadCache.findBestFit(allocationLength);
557  /* did we find an object? */
558  if (largeObject != NULL) {
559  /* remember the successful request */
560  requests++;
561  /* split and prepare this object for use */
562  return splitDeadObject(largeObject, allocationLength, LargeAllocationUnit);
563  }
564  return OREF_NULL; /* we couldn't get this */
565  }
566 
567  virtual DeadObject *donateObject(size_t allocationLength);
568 
569 protected:
570 
571  virtual void addDeadObject(DeadObject *object);
572  virtual void addDeadObject(char *object, size_t length);
573  virtual MemorySegment *allocateSegment(size_t requestLength, size_t minimumLength);
574  void expandOrCollect(size_t allocationLength);
575  void expandSegmentSet(size_t allocationLength);
576  virtual void prepareForSweep();
577  void completeSweepOperation();
578 
579  private:
580 
581  RexxObject *findObject(size_t allocationLength);
582 
583  DeadObjectPool deadCache; /* the set of large dead objects */
584  size_t requests; /* requests since last gc cycle. */
585  size_t smallestObject; // the smallest object in the set
586  size_t largestObject; // the largest object in the set
587 };
588 
589 
591 {
592  public:
593 
594  /* the default constructor */
597  virtual ~OldSpaceSegmentSet() { ; }
598  RexxObject *allocateObject(size_t allocationLength);
599 
600  void markOldSpaceObjects();
601 
602  protected:
603  virtual void addDeadObject(DeadObject *object);
604  virtual void addDeadObject(char *object, size_t length);
605  RexxObject *findObject(size_t allocationLength);
606 
607  private:
608  DeadObjectPool deadCache; /* the set of objects on the old dead chain */
609 };
610 
611 #endif
#define LengthToDeadPool(l)
#define DeadPools
#define NormalMemoryExpansionThreshold
#define MemorySegmentOverhead
size_t roundSegmentBoundary(size_t n)
#define NormalMemoryContractionThreshold
#define LargestSubpool
#define SegmentSize
#define RXROUNDUP(n, to)
Definition: RexxCore.h:221
#define OREF_NULL
Definition: RexxCore.h:61
#define LargeAllocationUnit
Definition: RexxMemory.hpp:76
#define MinimumObjectSize
Definition: RexxMemory.hpp:85
#define ObjectGrain
Definition: RexxMemory.hpp:74
void remove()
Definition: DeadObject.hpp:101
void add(DeadObject *obj)
Definition: DeadObject.hpp:161
DeadObject * findBestFit(size_t length)
Definition: DeadObject.cpp:66
void addSingle(DeadObject *obj)
Definition: DeadObject.hpp:262
DeadObject * findFit(size_t length)
Definition: DeadObject.hpp:193
DeadObject * getFirstSingle()
Definition: DeadObject.hpp:270
DeadObjectPool deadCache
RexxObject * findObject(size_t allocationLength)
virtual void prepareForSweep()
RexxObject * allocateObject(size_t allocationLength)
virtual void dumpMemoryProfile(FILE *outfile)
virtual ~LargeSegmentSet()
virtual DeadObject * donateObject(size_t allocationLength)
RexxObject * handleAllocationFailure(size_t allocationLength)
virtual MemorySegment * allocateSegment(size_t requestLength, size_t minimumLength)
void expandOrCollect(size_t allocationLength)
void expandSegmentSet(size_t allocationLength)
void completeSweepOperation()
virtual void addDeadObject(DeadObject *object)
MemorySegment * next
MemorySegment * previous
friend class OldSegmentSet
bool isInSegment(RexxObject *object)
void gatherObjectStats(MemoryStats *memStats, SegmentStats *stats)
bool isFirstBlock(char *addr)
bool isLastBlock(char *addr, size_t length)
void shrink(size_t delta)
void combine(MemorySegment *nextSegment)
DeadObject * lastDeadObject()
void insertAfter(MemorySegment *newSegment)
char segmentStart[8]
DeadObject * firstDeadObject()
void dump(const char *owner, size_t counter, FILE *keyfile, FILE *dumpfile)
DeadObject * createDeadObject()
bool isAdjacentTo(MemorySegment *seg)
DeadObject * firstObject()
friend class OldSegmentSet
void insertBefore(MemorySegment *newSegment)
MemorySegment(size_t segSize)
void dumpSegments(FILE *keyfile, FILE *dumpfile)
void activateEmptySegments()
bool isInSegmentSet(RexxObject *object)
MemorySegment anchor
const char * name
MemorySegment * findEmptySegment(size_t allocationLength)
SegmentSetID owner
void addSegment(MemorySegment *segment, bool createDeadObject=1)
void removeSegmentAndStorage(MemorySegment *segment)
MemorySegmentSet(RexxMemory *memObject, SegmentSetID id, const char *setName)
virtual size_t suggestMemoryContraction()
size_t calculateSegmentAllocation(size_t n)
void releaseEmptySegments(size_t releaseSize)
MemorySegment emptySegments
RexxObject * splitDeadObject(DeadObject *object, size_t allocationLength, size_t splitMinimum)
size_t totalFreeMemory()
MemorySegment * first()
void mergeSegments(size_t allocationLength)
MemorySegment * largestEmptySegment()
void combineEmptySegments(MemorySegment *front, MemorySegment *back)
void addSegments(size_t requiredSpace)
virtual MemorySegment * allocateSegment(size_t requestLength, size_t minimumLength)
virtual void completeSweepOperation()
virtual size_t suggestMemoryExpansion()
RexxMemory * memory
void releaseSegment(MemorySegment *segment)
virtual void prepareForSweep()
virtual void collectEmptySegments()
MemorySegment * getSegment(size_t requestLength, size_t minimumLength)
virtual ~MemorySegmentSet()
float freeMemoryPercentage()
void insertSegment(MemorySegment *segment)
bool is(SegmentSetID id)
void gatherStats(MemoryStats *memStats, SegmentStats *stats)
MemorySegment * splitSegment(size_t allocationLength)
void removeSegment(MemorySegment *segment)
virtual DeadObject * donateObject(size_t allocationLength)
virtual void dumpMemoryProfile(FILE *outfile)
void add(MemorySegment *segment)
MemorySegment * next(MemorySegment *segment)
bool newSegment(size_t requestLength, size_t minimumLength)
void validateObject(size_t bytes)
MemorySegment * largestActiveSegment()
virtual MemorySegment * donateSegment(size_t allocationLength)
virtual void addDeadObject(DeadObject *object)
size_t recommendedMaximumMemorySize()
virtual void addDeadObject(DeadObject *object)
virtual size_t suggestMemoryContraction()
RexxObject * findObject(size_t allocationLength)
MemorySegment * recoverSegment
RexxObject * splitNormalDeadObject(DeadObject *object, size_t allocationLength, size_t deadLength)
virtual DeadObject * donateObject(size_t allocationLength)
virtual void dumpMemoryProfile(FILE *outfile)
DeadObjectPool subpools[DeadPools]
virtual void prepareForSweep()
DeadObjectPool largeDead
RexxObject * handleAllocationFailure(size_t allocationLength)
RexxObject * findLargeDeadObject(size_t allocationLength)
void checkObjectOverlap(DeadObject *obj)
size_t lastUsedSubpool[DeadPools+1]
size_t mapLengthToDeadPool(size_t length)
size_t recommendedMemorySize()
virtual ~NormalSegmentSet()
virtual size_t suggestMemoryExpansion()
RexxObject * allocateObject(size_t allocationLength)
RexxObject * allocateObject(size_t allocationLength)
virtual ~OldSpaceSegmentSet()
virtual void addDeadObject(DeadObject *object)
RexxObject * findObject(size_t allocationLength)
DeadObjectPool deadCache
MemorySegment * newSegment(size_t requestLength, size_t minLength)
Definition: RexxMemory.cpp:740