1
2
3
4 package joeq.Allocator;
5
6 import joeq.Memory.Address;
7 import joeq.Memory.HeapAddress;
8 import joeq.Runtime.Debug;
9 import joeq.Runtime.SystemInterface;
10 import jwutil.util.Assert;
11
12 /***
13 * An implementation of an address queue that uses a circular buffer.
14 *
15 * @author John Whaley
16 * @version $Id: CircularAddressQueue.java 1941 2004-09-30 03:37:06Z joewhaley $
17 */
18 public class CircularAddressQueue implements AddressQueue {
19
20 public static final boolean TRACE = false;
21
22 /***
23 * Size of block (in words) to allocate when we need more space
24 * in a queue.
25 */
26 public static int QUEUE_WORDS = 262144;
27
28 /***
29 * Queue pointers.
30 */
31 HeapAddress queueStart, queueEnd;
32
33 /***
34 * Pointers to start and end of memory block.
35 */
36 HeapAddress blockStart, blockEnd;
37
38 /***
39 * Create a new CircularAddressQueue.
40 * Does not allocate any memory yet.
41 */
42 public CircularAddressQueue() {
43 super();
44 }
45
46
47
48
49 public void free() {
50 if (TRACE) Debug.writeln("Freeing work queue.");
51 if (!blockStart.isNull()) {
52 SystemInterface.sysfree(blockStart);
53 blockStart = blockEnd = queueStart = queueEnd = HeapAddress.getNull();
54 }
55 }
56
57
58
59
60 public void growQueue(int words) {
61
62 if (true) Debug.writeln("Growing work queue to size ", words * HeapAddress.size());
63 HeapAddress new_queue = (HeapAddress) SystemInterface.syscalloc(words * HeapAddress.size());
64 if (TRACE) Debug.writeln("New Queue start: ", new_queue);
65 if (new_queue.isNull())
66 HeapAllocator.outOfMemory();
67 if (TRACE) Debug.writeln("Queue start: ", queueStart);
68 if (TRACE) Debug.writeln("Queue end: ", queueEnd);
69 if (TRACE) Debug.writeln("Block start: ", blockStart);
70 if (TRACE) Debug.writeln("Block end: ", blockEnd);
71 int size = queueEnd.difference(queueStart);
72 if (size > 0) {
73 if (TRACE) Debug.writeln("Current size ", size);
74 Assert._assert(words * HeapAddress.size() > size);
75 SystemInterface.mem_cpy(new_queue, queueStart, size);
76 } else {
77 if (TRACE) Debug.writeln("Pointers are flipped");
78 int size2 = blockEnd.difference(queueStart);
79 if (TRACE) Debug.writeln("Size of first part: ", size2);
80 SystemInterface.mem_cpy(new_queue, queueStart, size2);
81 int size3 = queueEnd.difference(blockStart);
82 if (TRACE) Debug.writeln("Size of second part: ", size3);
83 SystemInterface.mem_cpy(new_queue.offset(size2), blockStart, size3);
84 size = size2 + size3;
85 }
86 if (TRACE) Debug.writeln("Freeing old queue");
87 SystemInterface.sysfree(blockStart);
88 queueStart = blockStart = new_queue;
89 blockEnd = (HeapAddress) blockStart.offset(words * HeapAddress.size());
90 queueEnd = (HeapAddress) queueStart.offset(size);
91 if (true) Debug.writeln("New Block end:", blockEnd);
92 if (true) Debug.writeln("New Queue end:", queueEnd);
93 }
94
95
96
97
98 public int size() {
99 int size = queueEnd.difference(queueStart);
100 if (size < 0) {
101 size = blockEnd.difference(queueStart) +
102 queueEnd.difference(blockStart);
103 }
104 return size / HeapAddress.size();
105 }
106
107
108
109
110 public int space() {
111 int size = queueEnd.difference(queueStart);
112 int space;
113 if (size < 0) {
114 space = -size;
115 } else {
116 space = blockEnd.difference(queueEnd) +
117 queueStart.difference(blockStart);
118 }
119 return space / HeapAddress.size();
120 }
121
122
123
124
125 public void push(Address a) {
126 if (TRACE) Debug.writeln("Adding to queue: ", a);
127 if (space() <= HeapAddress.size()) {
128
129 int size = blockEnd.difference(blockStart);
130 if (size == 0) size = QUEUE_WORDS;
131 else size = (QUEUE_WORDS *= 2);
132 growQueue(size);
133 }
134 if (TRACE) Debug.writeln("Adding at: ", queueEnd);
135 queueEnd.poke(a);
136 queueEnd = (HeapAddress) queueEnd.offset(HeapAddress.size());
137 if (queueEnd.difference(blockEnd) == 0) {
138 queueEnd = blockStart;
139 if (TRACE) Debug.writeln("Queue end pointer wrapped around to: ", queueEnd);
140 }
141 Assert._assert(queueEnd.difference(queueStart) != 0);
142 }
143
144
145
146
147 public Address pull() {
148 if (queueEnd.difference(queueStart) == 0) {
149 return HeapAddress.getNull();
150 }
151 if (TRACE) Debug.writeln("Pulling from: ", queueStart);
152 HeapAddress a = (HeapAddress) queueStart.peek();
153 queueStart = (HeapAddress) queueStart.offset(HeapAddress.size());
154 if (queueStart.difference(blockEnd) == 0) {
155 queueStart = blockStart;
156 if (TRACE) Debug.writeln("Queue start pointer wrapped around to: ", queueStart);
157 }
158 if (TRACE) Debug.writeln("Pulled from queue: ", a);
159 return a;
160 }
161
162
163
164
165 public Address peek() {
166 if (queueEnd.difference(queueStart) == 0) {
167 return HeapAddress.getNull();
168 }
169 Address a = (Address) queueStart.peek();
170 if (TRACE) Debug.writeln("Peeked from queue: ", a);
171 return a;
172 }
173 }