Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: Allocator/SimpleAllocator.java


1   // SimpleAllocator.java, created Mon Feb  5 23:23:19 2001 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package Allocator;
5   
6   import Bootstrap.PrimordialClassLoader;
7   import Clazz.jq_Class;
8   import Clazz.jq_InstanceMethod;
9   import GC.GCBits;
10  import Memory.Address;
11  import Memory.HeapAddress;
12  import Run_Time.SystemInterface;
13  import Util.Assert;
14  
15  /**
16   * SimpleAllocator
17   *
18   * @author  John Whaley <jwhaley@alum.mit.edu>
19   * @version $Id: SimpleAllocator.java,v 1.30 2003/05/12 10:04:52 joewhaley Exp $
20   */
21  
22  public class SimpleAllocator extends HeapAllocator {
23  
24      /**
25       * Size of blocks allocated from the OS.
26       */
27      public static final int BLOCK_SIZE = 2097152;
28  
29      /**
30       * Maximum memory, in bytes, to be allocated from the OS.
31       */
32      public static /*final*/ int MAX_MEMORY = 67108864;
33  
34      /**
35       * Threshold for direct OS allocation.  When an array overflows the current block
36       * and is larger than this size, it is allocated directly from the OS.
37       */
38      public static final int LARGE_THRESHOLD = 262144;
39  
40      /**
41       * Pointers to the start, current, and end of the heap.
42       */
43      private HeapAddress heapFirst, heapCurrent, heapEnd;
44  
45      /**
46       * GC information for the current block.
47       */
48      private GCBits gcBits;
49  
50      /**
51       * Perform initialization for this allocator.  This will be called before any other methods.
52       * This allocates an initial block of memory from the OS and sets up relevant pointers.
53       *
54       * @throws OutOfMemoryError if there is not enough memory for initialization
55       */
56      public final void init() throws OutOfMemoryError {
57          heapCurrent = heapFirst = (HeapAddress) SystemInterface.syscalloc(BLOCK_SIZE);
58          if (heapCurrent.isNull())
59              HeapAllocator.outOfMemory();
60          heapEnd = (HeapAddress) heapFirst.offset(BLOCK_SIZE - 2 * HeapAddress.size());
61          installGCBits();
62      }
63  
64      /**
65       * Allocates a new block of memory from the OS, sets the current block to
66       * point to it, makes the new block the current block, and allocates and
67       * installs the GC structures.
68       *
69       * @throws OutOfMemoryError if there is not enough memory for initialization
70       */
71      private void allocateNewBlock() {
72          if (totalMemory() >= MAX_MEMORY) HeapAllocator.outOfMemory();
73          heapCurrent = (HeapAddress) SystemInterface.syscalloc(BLOCK_SIZE);
74          if (heapCurrent.isNull())
75              HeapAllocator.outOfMemory();
76          // GCBits address of current block already filled
77          heapEnd.offset(HeapAddress.size()).poke(heapCurrent);
78          // address for per block GCBits plus address for next block
79          heapEnd = (HeapAddress) heapCurrent.offset(BLOCK_SIZE - 2 * HeapAddress.size());
80          installGCBits();
81      }
82  
83      /**
84       * Allocates and installs the GC structures for the current block.
85       */
86      private void installGCBits() {
87          // install gc bits for next block.
88          gcBits = null;
89          // NOTE: allocations caused by the next line don't have gc bits set.
90          gcBits = new GCBits(heapCurrent, heapEnd);
91          heapEnd.poke(HeapAddress.addressOf(gcBits));
92      }
93  
94      /**
95       * Returns an estimate of the amount of free memory available.
96       *
97       * @return bytes of free memory
98       */
99      public final int freeMemory() {
100         return heapEnd.difference(heapCurrent);
101     }
102 
103     /**
104      * Returns an estimate of the total memory allocated (both used and unused).
105      *
106      * @return bytes of memory allocated
107      */
108     public final int totalMemory() {
109         int total = 0;
110         HeapAddress ptr = heapFirst;
111         while (!ptr.isNull()) {
112             total += BLOCK_SIZE;
113             ptr = (HeapAddress) ptr.offset(BLOCK_SIZE - HeapAddress.size()).peek();
114         }
115         return total;
116     }
117 
118     /**
119      * Allocate an object with the default alignment.
120      * If the object cannot be allocated due to lack of memory, throws OutOfMemoryError.
121      *
122      * @param size size of object to allocate (including object header), in bytes
123      * @param vtable vtable pointer for new object
124      * @return new uninitialized object
125      * @throws OutOfMemoryError if there is insufficient memory to perform the operation
126      */
127     public final Object allocateObject(int size, Object vtable) throws OutOfMemoryError {
128         if (size < ObjectLayout.OBJ_HEADER_SIZE) // size overflow! become minus!
129             HeapAllocator.outOfMemory();
130         //jq.Assert((size & 0x3) == 0);
131         size = (size + 3) & ~3; // align size
132         HeapAddress addr = (HeapAddress) heapCurrent.offset(ObjectLayout.OBJ_HEADER_SIZE);
133         heapCurrent = (HeapAddress) heapCurrent.offset(size);
134         if (heapEnd.difference(heapCurrent) < 0) {
135             // not enough space (rare path)
136             Assert._assert(size < BLOCK_SIZE - 2 * HeapAddress.size());
137             heapCurrent = (HeapAddress) heapCurrent.offset(-size);
138             // consult FreeMemManager for free memory in previous blocks
139             addr = (HeapAddress)FreeMemManager.getFreeMem(size + ObjectLayout.OBJ_HEADER_SIZE);
140             if (addr != null) {
141                 addr = (HeapAddress) addr.offset(ObjectLayout.OBJ_HEADER_SIZE);
142             } else {
143                 allocateNewBlock();
144                 addr = (HeapAddress) heapCurrent.offset(ObjectLayout.OBJ_HEADER_SIZE);
145                 heapCurrent = (HeapAddress) heapCurrent.offset(size);
146             }
147         }
148         // fast path
149         addr.offset(ObjectLayout.VTABLE_OFFSET).poke(HeapAddress.addressOf(vtable));
150         if (gcBits != null) {
151             gcBits.set((HeapAddress) addr.offset(-ObjectLayout.OBJ_HEADER_SIZE));
152         }
153         return addr.asObject();
154     }
155 
156     /**
157      * Allocate an object such that the first field is 8-byte aligned.
158      * If the object cannot be allocated due to lack of memory, throws OutOfMemoryError.
159      *
160      * @param size size of object to allocate (including object header), in bytes
161      * @param vtable vtable pointer for new object
162      * @return new uninitialized object
163      * @throws OutOfMemoryError if there is insufficient memory to perform the operation
164      */
165     public final Object allocateObjectAlign8(int size, Object vtable) throws OutOfMemoryError {
166         heapCurrent = (HeapAddress) heapCurrent.offset(ObjectLayout.OBJ_HEADER_SIZE).align(3).offset(-ObjectLayout.OBJ_HEADER_SIZE);
167         return allocateObject(size, vtable);
168     }
169 
170     /**
171      * Allocate an array with the default alignment.
172      * If length is negative, throws NegativeArraySizeException.
173      * If the array cannot be allocated due to lack of memory, throws OutOfMemoryError.
174      *
175      * @param length length of new array
176      * @param size size of array to allocate (including array header), in bytes
177      * @param vtable vtable pointer for new array
178      * @return new array
179      * @throws NegativeArraySizeException if length is negative
180      * @throws OutOfMemoryError if there is insufficient memory to perform the operation
181      */
182     public final Object allocateArray(int length, int size, Object vtable) throws OutOfMemoryError, NegativeArraySizeException {
183         if (length < 0) throw new NegativeArraySizeException(length + " < 0");
184         if (size < ObjectLayout.ARRAY_HEADER_SIZE) // size overflow!
185             HeapAllocator.outOfMemory();
186         size = (size + 3) & ~3; // align size
187         HeapAddress addr = (HeapAddress) heapCurrent.offset(ObjectLayout.ARRAY_HEADER_SIZE);
188         heapCurrent = (HeapAddress) heapCurrent.offset(size);
189         if (heapEnd.difference(heapCurrent) < 0) {
190             // not enough space (rare path)
191             heapCurrent = (HeapAddress) heapCurrent.offset(-size);
192             if (size > LARGE_THRESHOLD) {
193                 // special large-object allocation
194                 addr = (HeapAddress) SystemInterface.syscalloc(size);
195                 if (addr.isNull())
196                     outOfMemory();
197                 addr = (HeapAddress) addr.offset(ObjectLayout.ARRAY_HEADER_SIZE);
198                 addr.offset(ObjectLayout.ARRAY_LENGTH_OFFSET).poke4(length);
199                 addr.offset(ObjectLayout.VTABLE_OFFSET).poke(HeapAddress.addressOf(vtable));
200                 // TODO: gc ?!?
201                 return addr.asObject();
202             } else {
203                 Assert._assert(size < BLOCK_SIZE - 2 * HeapAddress.size());
204                 // consult FreeMemManager for free memory in previous blocks
205                 addr = (HeapAddress)FreeMemManager.getFreeMem(size + ObjectLayout.OBJ_HEADER_SIZE);
206                 if (addr != null) {
207                     addr = (HeapAddress) addr.offset(ObjectLayout.ARRAY_HEADER_SIZE);
208                 } else {
209                     allocateNewBlock();
210                     addr = (HeapAddress) heapCurrent.offset(ObjectLayout.ARRAY_HEADER_SIZE);
211                     heapCurrent = (HeapAddress) heapCurrent.offset(size);
212                 }
213             }
214         }
215         // fast path
216         addr.offset(ObjectLayout.ARRAY_LENGTH_OFFSET).poke4(length);
217         addr.offset(ObjectLayout.VTABLE_OFFSET).poke(HeapAddress.addressOf(vtable));
218         if (gcBits != null) {
219             gcBits.set((HeapAddress) addr.offset(-ObjectLayout.ARRAY_HEADER_SIZE));
220         }
221         return addr.asObject();
222     }
223 
224     /**
225      * Allocate an array such that the elements are 8-byte aligned.
226      * If length is negative, throws NegativeArraySizeException.
227      * If the array cannot be allocated due to lack of memory, throws OutOfMemoryError.
228      *
229      * @param length length of new array
230      * @param size size of array to allocate (including array header), in bytes
231      * @param vtable vtable pointer for new array
232      * @return new array
233      * @throws NegativeArraySizeException if length is negative
234      * @throws OutOfMemoryError if there is insufficient memory to perform the operation
235      */
236     public final Object allocateArrayAlign8(int length, int size, Object vtable) throws OutOfMemoryError, NegativeArraySizeException {
237         heapCurrent = (HeapAddress) heapCurrent.offset(ObjectLayout.ARRAY_HEADER_SIZE).align(3).offset(-ObjectLayout.ARRAY_HEADER_SIZE);
238         return allocateArray(length, size, vtable);
239     }
240 
241     public final void collect() {
242         // nothing for now.
243     }
244 
245     public final void processPtrField(Address a) {
246         // nothing for now.
247     }
248     
249     public static final jq_Class _class;
250     public static final jq_InstanceMethod _allocateObject;
251     public static final jq_InstanceMethod _allocateObjectAlign8;
252     public static final jq_InstanceMethod _allocateArray;
253     public static final jq_InstanceMethod _allocateArrayAlign8;
254 
255     static {
256         _class = (jq_Class) PrimordialClassLoader.loader.getOrCreateBSType("LAllocator/SimpleAllocator;");
257         _allocateObject = _class.getOrCreateInstanceMethod("allocateObject", "(ILjava/lang/Object;)Ljava/lang/Object;");
258         _allocateObjectAlign8 = _class.getOrCreateInstanceMethod("allocateObjectAlign8", "(ILjava/lang/Object;)Ljava/lang/Object;");
259         _allocateArray = _class.getOrCreateInstanceMethod("allocateArray", "(IILjava/lang/Object;)Ljava/lang/Object;");
260         _allocateArrayAlign8 = _class.getOrCreateInstanceMethod("allocateArrayAlign8", "(IILjava/lang/Object;)Ljava/lang/Object;");
261     }
262 }