Added variable and constant to common.retro module
[retro.git] / toka / gc.c
blob637695782ff8de9d381865a087f7aa375a7d4709
1 /******************************************************
2 * Toka
4 *|F|
5 *|F| FILE: gc.c
6 *|F|
8 * Copyright (c) 2006, 2007 Charles R. Childers
10 * Permission to use, copy, modify, and distribute this
11 * software for any purpose with or without fee is hereby
12 * granted, provided that the above copyright notice and
13 * this permission notice appear in all copies.
15 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR
16 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
19 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
20 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
21 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
22 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
23 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * OF THIS SOFTWARE.
25 ******************************************************/
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
31 #include "toka.h"
33 extern VM_STACK data, address, alternate;
37 /******************************************************
38 *|F| Variables:
39 *|F| GCITEM gc_list[128]
40 *|F| Holds the list of items marked as garbage
41 *|F|
42 *|F| long gc_depth
43 *|F| A pointer to the top of the garbage collection
44 *|F| list
45 *|F|
46 *|F| GCITEM gc_trash[128]
47 *|F| Holds the short list of items marked as garbage
48 *|F|
49 *|F| long gc_tdepth
50 *|F| A pointer to the top of the short garbage
51 *|F| collection list
52 *|F|
53 *|F| long gc_used
54 *|F| Contains the total size of all currently used
55 *|F| memory, including permanent quotes.
56 *|F|
57 *|F| long gc_objects
58 *|F| Contains the total number of objects that are
59 *|F| currently existing, including permanent ones.
60 *|F|
61 ******************************************************/
62 long gc_used = 0, gc_objects = 0;
63 GCITEM gc_list[128]; long gc_depth = 0;
64 GCITEM gc_trash[128]; long gc_tdepth = 0;
68 /******************************************************
69 *|F| gc_alloc(long items, long size, long type)
70 *|F| Allocate the requested memory and add it to the
71 *|F| garbage collection list.
72 *|F| If type is set to GC_MEM, add to the normal garbage
73 *|F| collection list. If set to GC_TRASH, add to the short
74 *|F| list of known garbage items which can be safely
75 *|F| freed at the next gc().
76 *|F| If the allocation fails, gc() is called, and the
77 *|F| allocation is retried. If it still fails, an
78 *|F| error is reported and Toka is terminated.
79 *|F|
80 ******************************************************/
81 void *gc_alloc(long items, long size, long type)
83 void *memory;
85 if (gc_depth == 127 || gc_tdepth == 127)
86 gc();
88 memory = calloc((int)items, (int)size);
90 if (memory == NULL)
92 gc();
93 memory = calloc((int)items, (int)size);
94 if (memory == NULL)
95 error(ERROR_NO_MEM);
98 memset(memory, 0, size * items);
100 if (type == GC_MEM)
102 gc_list[gc_depth].xt = (Inst)memory;
103 gc_list[gc_depth].size = size * items;
104 gc_depth++;
106 if (type == GC_TEMP)
108 gc_trash[gc_tdepth].xt = (Inst)memory;
109 gc_trash[gc_tdepth].size = size * items;
110 gc_tdepth++;
113 gc_used += size * items;
114 gc_objects++;
116 return memory;
121 /******************************************************
122 *|G| keep ( a-a ) Mark quotes/allocated memory
123 *|G| as permanent.
125 *|F| gc_keep()
126 *|F| Remove the specified address (and any childern it
127 *|F| has registered) from the garbage collection list.
128 *|F| If the TOS is not an allocated address, this will
129 *|F| silently ignore it.
130 *|F|
131 ******************************************************/
132 void gc_keep()
134 long a, which;
136 Inst item = (Inst)TOS;
137 which = -1;
139 for (a = 0; a != gc_depth; a++)
141 if (gc_list[a].xt == item)
142 which = a;
145 if (which != -1)
147 for (a = gc_depth; a > which; a--)
148 gc_depth--;
154 /******************************************************
155 *|G| gc ( - ) Clean the garbage
157 *|F| gc()
158 *|F| Free the oldest allocations on the garbage list.
159 *|F| Will free up to 64 trash entries and 32 normal
160 *|F| entries per call.
161 *|F|
162 ******************************************************/
163 void gc()
165 long a, b;
167 /* Allocations known to be temporary */
168 if (gc_tdepth < 64)
169 b = 0;
170 else
171 b = 64;
173 for (a = 0; a != b; a++)
175 free(gc_trash[a].xt);
176 gc_used -= gc_trash[a].size;
177 gc_list[a].xt = 0;
178 gc_objects--;
181 if (b != gc_tdepth)
183 for (a = 0; a != gc_tdepth; a++)
185 gc_trash[a].xt = gc_trash[a+b].xt;
186 gc_trash[a].size = gc_trash[a+b].size;
190 gc_tdepth -= b;
193 /* General Allocations */
194 if (gc_depth < 32)
195 b = 0;
196 else
197 b = 32;
199 for (a = 0; a != b; a++)
201 free(gc_list[a].xt);
202 gc_used -= gc_list[a].size;
203 gc_list[a].xt = 0;
204 gc_objects--;
207 if (b != gc_depth)
209 for (a = 0; a != gc_depth; a++)
211 gc_list[a].xt = gc_list[a+b].xt;
212 gc_list[a].size = gc_list[a+b].size;
216 gc_depth -= b;
221 /******************************************************
222 *|G| malloc ( n-a ) Allocate 'n' bytes of memory
224 *|F| toka_malloc()
225 *|F| Allocate TOS bytes of memory. Returns a pointer to
226 *|F| the allocated memory.
227 *|F|
228 ******************************************************/
229 void toka_malloc()
231 TOS = (long)gc_alloc(TOS, sizeof(char), GC_MEM);