DeadObject.cpp
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 DeadObject.c */
40 /* */
41 /* Primitive DeadObject management code */
42 /* */
43 /******************************************************************************/
44 
45 #include <stdlib.h>
46 #include <string.h>
47 #include "RexxCore.h"
48 #include "RexxMemory.hpp"
49 #include "Interpreter.hpp"
50 
52 /******************************************************************************/
53 /* Function: Dump statistics for this dead object pool. */
54 /******************************************************************************/
55 {
56 #ifdef MEMPROFILE /* doing memory profiling */
57  fprintf(outFile, "Statistics for Dead Object Pool %s\n, id");
58  fprintf(outFile, " Total memory allocations: %d\n", allocationCount);
59  fprintf(outFile, " Unsuccessful requests: %d\n", allocationMisses);
60  fprintf(outFile, " Successful requests: %d\n", allocationHits);
61  fprintf(outFile, " Objects added back to the pool\n", allocationReclaim);
62 #endif
63 }
64 
65 
67 /******************************************************************************/
68 /* Function: Find an object that is the best fit for a requested length. */
69 /* To get the best fit, we either want an object that fits well enough that */
70 /* we don't need to create a trailing dead object from the remainder, OR */
71 /* we return the largest possible object so that we can create the largest */
72 /* possible remainder object. */
73 /******************************************************************************/
74 {
75  DeadObject *newObject = anchor.next;
76  DeadObject *largest = NULL;
77  size_t largestSize = 0;
78  size_t deadLength = newObject->getObjectSize();
79 
80  for (; deadLength != 0; deadLength = newObject->getObjectSize()) {
81  if (deadLength >= length) {
82  /* if within an allocation unit of the request size (which should */
83  /* be common, since we round to a higher boundary for */
84  /* large allocations), use this block */
85  if ((deadLength - length) < VeryLargeObjectGrain) {
86  newObject->remove();
87  logHit();
88  return newObject;
89  }
90  /* keep track of the largest block. We want to */
91  /* suballocate that if we can't find a good fit. */
92  else if (deadLength > largestSize) {
93  largestSize = deadLength;
94  largest = newObject;
95  }
96  }
97  newObject = newObject->next;
98  }
99  /* we didn't find a close fit, so use the largest that will */
100  /* work, if we found one. */
101  if (largest != NULL) {
102  logHit();
103  largest->remove();
104  }
105  else {
106  logMiss();
107  }
108  return largest;
109 }
110 
111 
113 /******************************************************************************/
114 /* Function: Find the smallest object in the pool that will hold the length. */
115 /******************************************************************************/
116 {
117  DeadObject *newObject = anchor.next;
118  DeadObject *smallest = NULL;
119  size_t smallestSize = MaximumObjectSize;
120 
121  while (newObject->isReal()) {
122  size_t deadLength = newObject->getObjectSize();
123  /* does this fit the request size? */
124  if (deadLength >= minSize && deadLength < smallestSize) {
125  /* remember this for the end. */
126  smallestSize = deadLength;
127  smallest = newObject;
128  /* did we get an exact fit? No need to look at any */
129  /* others then. */
130  if (deadLength == minSize) {
131  break;
132  }
133  }
134  newObject = newObject->next;
135  }
136  /* if we found a fit, remove the block and return it. */
137  if (smallest != NULL) {
138  smallest->remove();
139  logHit();
140  }
141  else {
142  logMiss();
143  }
144  return smallest;
145 }
146 
147 
149 /******************************************************************************/
150 /* Function: Add an object to the pool sorted by size (ascending order). */
151 /******************************************************************************/
152 {
153 // checkObjectOverlap(obj);
154 // checkObjectGrain(obj);
155  /* we start with the first element in the chain as the */
156  /* insertion point. If the chain is empty, we'll terminate the */
157  /* loop immediately and use the anchor as the insertion point, */
158  /* which gives us the result we want. */
159  DeadObject *insertPoint = anchor.next;
160  size_t size = obj->getObjectSize();
161 
162  while (insertPoint->isReal()) {
163  /* if the current block is larger than the one we're */
164  /* inserting, we've found our spot. */
165  if (insertPoint->getObjectSize() >= size) {
166  break;
167  }
168  insertPoint = insertPoint->next;
169  }
170  /* insert this at the given point */
171  insertPoint->insertBefore(obj);
172 }
173 
174 
176 /******************************************************************************/
177 /* Function: Add an object to the pool sorted by address (ascending order). */
178 /******************************************************************************/
179 {
180 // checkObjectOverlap(obj);
181 // checkObjectGrain(obj);
182  /* we start with the first element in the chain as the */
183  /* insertion point. If the chain is empty, we'll terminate the */
184  /* loop immediately and use the anchor as the insertion point, */
185  /* which gives us the result we want. */
186  DeadObject *insertPoint = anchor.next;
187 
188  while (insertPoint->isReal()) {
189  /* if the current block's address is larger than the one we're */
190  /* inserting, we've found our spot. */
191  if (insertPoint > obj) {
192  break;
193  }
194  insertPoint = insertPoint->next;
195  }
196  /* insert this at the given point */
197  insertPoint->insertBefore(obj);
198 }
199 
200 
202 /******************************************************************************/
203 /* Function: Debug validity check of object added to a dead pool. */
204 /******************************************************************************/
205 {
206  if (!IsObjectGrained(obj))
207  {
208  Interpreter::logicError("Object aligned on improper boundary");
209  }
210 }
211 
213 /******************************************************************************/
214 /* Function: Debug validity check of object added to a dead pool. */
215 /******************************************************************************/
216 {
217  DeadObject *check = anchor.next;
218 
219  while (check != NULL && check->isReal()) {
220  if (check->overlaps(obj)) {
221  printf("Object at %p for length %lu overlaps object at %p for length %lu\n", obj, obj->getObjectSize(), check, check->getObjectSize());
222  Interpreter::logicError("Overlapping dead objects added to the cache.");
223  }
224  check = check->next;
225  }
226 }
#define VeryLargeObjectGrain
Definition: RexxMemory.hpp:80
#define MaximumObjectSize
Definition: RexxMemory.hpp:86
#define IsObjectGrained(o)
Definition: RexxMemory.hpp:92
void remove()
Definition: DeadObject.hpp:101
bool overlaps(DeadObject *o)
Definition: DeadObject.hpp:117
void insertBefore(DeadObject *newDead)
Definition: DeadObject.hpp:94
bool isReal()
Definition: DeadObject.hpp:106
DeadObject * next
Definition: DeadObject.hpp:124
size_t getObjectSize()
Definition: DeadObject.hpp:85
DeadObject * findSmallestFit(size_t minSize)
Definition: DeadObject.cpp:112
void dumpMemoryProfile(FILE *outfile)
Definition: DeadObject.cpp:51
void checkObjectGrain(DeadObject *obj)
Definition: DeadObject.cpp:201
void addSortedBySize(DeadObject *obj)
Definition: DeadObject.cpp:148
void checkObjectOverlap(DeadObject *obj)
Definition: DeadObject.cpp:212
DeadObject anchor
Definition: DeadObject.hpp:305
DeadObject * findBestFit(size_t length)
Definition: DeadObject.cpp:66
void addSortedByLocation(DeadObject *obj)
Definition: DeadObject.cpp:175
static void logicError(const char *desc)