Mercurial > repos > rhope
comparison runtime/object.c @ 186:ba35ab624ec2
Add support for raw C function output from C backend as well as an option to use Boehm-GC instead of reference counting
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 07 Oct 2011 00:10:02 -0700 |
parents | a68e6828d896 |
children |
comparison
equal
deleted
inserted
replaced
185:4580c08fd4e8 | 186:ba35ab624ec2 |
---|---|
1 #include "object.h" | 1 #include "object.h" |
2 #include "builtin.h" | 2 #include "builtin.h" |
3 #ifdef USE_GC | |
4 #include <gc/gc.h> | |
5 #else | |
3 #include <stdlib.h> | 6 #include <stdlib.h> |
7 #ifndef USE_MALLOC | |
8 #include "fixed_alloc.h" | |
9 #endif | |
10 #endif | |
4 #include <string.h> | 11 #include <string.h> |
5 #include <stdio.h> | 12 #include <stdio.h> |
6 #include "fixed_alloc.h" | |
7 | 13 |
8 blueprint ** registered_types = NULL; | 14 blueprint ** registered_types = NULL; |
9 uint32_t max_registered_type = 0; | 15 uint32_t max_registered_type = 0; |
10 uint32_t type_storage = 0; | 16 uint32_t type_storage = 0; |
11 | 17 |
127 return EXCEPTION_RETURN; | 133 return EXCEPTION_RETURN; |
128 }*/ | 134 }*/ |
129 | 135 |
130 object * alloc_object(blueprint * bp) | 136 object * alloc_object(blueprint * bp) |
131 { | 137 { |
138 #ifdef USE_GC | |
139 return GC_malloc(bp->boxed_size); | |
140 #else | |
141 #ifdef USE_MALLOC | |
142 return malloc(bp->boxed_size); | |
143 #else | |
132 return falloc(bp->boxed_size, manager); | 144 return falloc(bp->boxed_size, manager); |
133 //return malloc(bp->boxed_size); | 145 #endif |
134 } | 146 #endif |
135 | 147 } |
148 | |
149 #ifndef USE_GC | |
136 void dealloc_object(blueprint * bp, object * obj) | 150 void dealloc_object(blueprint * bp, object * obj) |
137 { | 151 { |
152 #ifdef USE_MALLOC | |
153 free(obj); | |
154 #else | |
138 ffree(obj, bp->boxed_size, manager); | 155 ffree(obj, bp->boxed_size, manager); |
139 } | 156 #endif |
157 } | |
158 #endif | |
140 | 159 |
141 object * new_object(uint32_t type) | 160 object * new_object(uint32_t type) |
142 { | 161 { |
143 blueprint * bp; | 162 blueprint * bp; |
144 object * ret; | 163 object * ret; |
153 object * ret; | 172 object * ret; |
154 ret = alloc_object(bp); | 173 ret = alloc_object(bp); |
155 if(ret) | 174 if(ret) |
156 { | 175 { |
157 ret->bprint = bp; | 176 ret->bprint = bp; |
177 #ifndef USE_GC | |
158 rh_atomic_set(ret, refcount, 1); | 178 rh_atomic_set(ret, refcount, 1); |
179 #endif | |
159 memset(((char *)ret) + sizeof(object), '\0', bp->size); | 180 memset(((char *)ret) + sizeof(object), '\0', bp->size); |
160 bp->init(ret); | 181 bp->init(ret); |
161 } else { | 182 } else { |
162 fprintf(stderr, "Could not allocate new object with size %d\n", bp->boxed_size); | 183 fprintf(stderr, "Could not allocate new object with size %d\n", bp->boxed_size); |
163 } | 184 } |
168 { | 189 { |
169 blueprint *bp; | 190 blueprint *bp; |
170 multisize * ret; | 191 multisize * ret; |
171 if(type >= max_registered_type || !registered_types[type]) | 192 if(type >= max_registered_type || !registered_types[type]) |
172 return NULL; | 193 return NULL; |
194 #ifdef USE_GC | |
195 ret = GC_malloc(sizeof(multisize) + size); | |
196 #else | |
197 #ifdef USE_MALLOC | |
198 ret = malloc(sizeof(multisize) + size); | |
199 #else | |
173 ret = falloc(sizeof(multisize) + size, manager); | 200 ret = falloc(sizeof(multisize) + size, manager); |
201 #endif | |
202 #endif | |
174 if(ret) | 203 if(ret) |
175 { | 204 { |
176 bp = registered_types[type]; | 205 bp = registered_types[type]; |
177 ret->base.bprint = bp; | 206 ret->base.bprint = bp; |
178 ret->size = size; | 207 ret->size = size; |
208 #ifndef USE_GC | |
179 rh_atomic_set(&(ret->base), refcount, 1); | 209 rh_atomic_set(&(ret->base), refcount, 1); |
210 #endif | |
180 memset(((char *)ret) + sizeof(multisize), '\0', size); | 211 memset(((char *)ret) + sizeof(multisize), '\0', size); |
181 bp->init((object *)ret); | 212 bp->init((object *)ret); |
182 } | 213 } |
183 return ret; | 214 return ret; |
184 } | 215 } |
186 object * copy_object(object * tocopy) | 217 object * copy_object(object * tocopy) |
187 { | 218 { |
188 object * copy; | 219 object * copy; |
189 multisize * mcopy, *mtocopy; | 220 multisize * mcopy, *mtocopy; |
190 blueprint * bp; | 221 blueprint * bp; |
222 #ifndef USE_GC | |
191 if(rh_atomic_get(tocopy, refcount) == 1) | 223 if(rh_atomic_get(tocopy, refcount) == 1) |
192 return tocopy; | 224 return tocopy; |
225 #endif | |
193 bp = get_blueprint(tocopy); | 226 bp = get_blueprint(tocopy); |
194 if(bp->size < 0) { | 227 if(bp->size < 0) { |
195 mtocopy = (multisize *)tocopy; | 228 mtocopy = (multisize *)tocopy; |
229 #ifdef USE_GC | |
230 mcopy = GC_malloc(sizeof(multisize) + mtocopy->size); | |
231 #else | |
232 #ifdef USE_MALLOC | |
233 mcopy = malloc(sizeof(multisize) + mtocopy->size); | |
234 #else | |
196 mcopy = falloc(sizeof(multisize) + mtocopy->size, manager); | 235 mcopy = falloc(sizeof(multisize) + mtocopy->size, manager); |
236 #endif | |
237 #endif | |
197 mcopy->size = mtocopy->size; | 238 mcopy->size = mtocopy->size; |
198 memcpy(((char *)mcopy)+sizeof(multisize), ((char *)mtocopy)+sizeof(multisize), mtocopy->size); | 239 memcpy(((char *)mcopy)+sizeof(multisize), ((char *)mtocopy)+sizeof(multisize), mtocopy->size); |
199 copy = (object *)mcopy; | 240 copy = (object *)mcopy; |
200 } else { | 241 } else { |
201 copy = alloc_object(bp); | 242 copy = alloc_object(bp); |
202 memcpy(((char *)copy) + sizeof(object), ((char *)tocopy)+sizeof(object), bp->size); | 243 memcpy(((char *)copy) + sizeof(object), ((char *)tocopy)+sizeof(object), bp->size); |
203 } | 244 } |
204 copy->bprint = bp; | 245 copy->bprint = bp; |
246 #ifndef USE_GC | |
205 rh_atomic_set(copy, refcount, 1); | 247 rh_atomic_set(copy, refcount, 1); |
248 #endif | |
206 bp->copy(copy); | 249 bp->copy(copy); |
207 release_ref(tocopy); | 250 release_ref(tocopy); |
208 return copy; | 251 return copy; |
209 } | 252 } |
210 | 253 |
215 if(!bp->boxed_size) | 258 if(!bp->boxed_size) |
216 return NULL; //We don't know how big a naked multi-size object is so we can't do anything with it | 259 return NULL; //We don't know how big a naked multi-size object is so we can't do anything with it |
217 dest = alloc_object(bp); | 260 dest = alloc_object(bp); |
218 memcpy(((char *)dest) + sizeof(object), rawdata, bp->size); | 261 memcpy(((char *)dest) + sizeof(object), rawdata, bp->size); |
219 dest->bprint = bp; | 262 dest->bprint = bp; |
263 #ifndef USE_GC | |
220 rh_atomic_set(dest, refcount, 1); | 264 rh_atomic_set(dest, refcount, 1); |
265 #endif | |
221 bp->copy(dest); | 266 bp->copy(dest); |
222 return dest; | 267 return dest; |
223 } | 268 } |
224 | 269 |
225 void boxed_to_naked(object * src, void * dest) | 270 void boxed_to_naked(object * src, void * dest) |
229 return; //We don't know how big a naked multi-size object is so we can't do anything with it | 274 return; //We don't know how big a naked multi-size object is so we can't do anything with it |
230 memcpy(dest, ((char *)src) + sizeof(object), bp->size); | 275 memcpy(dest, ((char *)src) + sizeof(object), bp->size); |
231 bp->copy(src); | 276 bp->copy(src); |
232 } | 277 } |
233 | 278 |
279 #ifndef USE_GC | |
234 void release_ref(object * obj) | 280 void release_ref(object * obj) |
235 { | 281 { |
236 if(rh_atomic_sub_testzero(obj, refcount, 1)) | 282 if(rh_atomic_sub_testzero(obj, refcount, 1)) |
237 get_blueprint(obj)->free(obj); | 283 get_blueprint(obj)->free(obj); |
238 } | 284 } |
285 #endif | |
239 | 286 |
240 void check_type_storage(type) | 287 void check_type_storage(type) |
241 { | 288 { |
242 uint32_t type_storage_temp; | 289 uint32_t type_storage_temp; |
243 blueprint ** temp; | 290 blueprint ** temp; |
244 if(type >= type_storage) | 291 if(type >= type_storage) |
245 if(type_storage) | 292 if(type_storage) |
246 { | 293 { |
247 type_storage_temp = (type + (type_storage >> 1)); | 294 type_storage_temp = (type + (type_storage >> 1)); |
295 #ifdef USE_GC | |
296 temp = GC_realloc(registered_types, type_storage_temp * sizeof(blueprint *)); | |
297 #else | |
248 temp = realloc(registered_types, type_storage_temp * sizeof(blueprint *)); | 298 temp = realloc(registered_types, type_storage_temp * sizeof(blueprint *)); |
299 #endif | |
249 if(temp) | 300 if(temp) |
250 { | 301 { |
251 registered_types = temp; | 302 registered_types = temp; |
252 memset(registered_types + type_storage, '\0', (type_storage_temp - type_storage) * sizeof(blueprint *)); | 303 memset(registered_types + type_storage, '\0', (type_storage_temp - type_storage) * sizeof(blueprint *)); |
253 type_storage = type_storage_temp; | 304 type_storage = type_storage_temp; |
254 } | 305 } |
255 else | 306 else |
256 { | 307 { |
308 #ifndef USE_GC | |
257 free(registered_types); | 309 free(registered_types); |
310 #endif | |
258 fprintf(stderr, "Couldn't allocate %d bytes for type storage array\n", type_storage_temp * sizeof(blueprint *)); | 311 fprintf(stderr, "Couldn't allocate %d bytes for type storage array\n", type_storage_temp * sizeof(blueprint *)); |
259 exit(-1); | 312 exit(-1); |
260 } | 313 } |
261 } else { | 314 } else { |
262 | 315 |
263 if(type < INITIAL_TYPE_STORAGE) | 316 if(type < INITIAL_TYPE_STORAGE) |
264 type_storage =INITIAL_TYPE_STORAGE; | 317 type_storage =INITIAL_TYPE_STORAGE; |
265 else | 318 else |
266 type_storage = type + 8; | 319 type_storage = type + 8; |
320 #ifdef USE_GC | |
321 registered_types = GC_malloc(type_storage * sizeof(blueprint *)); | |
322 #else | |
267 registered_types = malloc(type_storage * sizeof(blueprint *)); | 323 registered_types = malloc(type_storage * sizeof(blueprint *)); |
324 #endif | |
325 | |
268 if(registered_types) | 326 if(registered_types) |
269 memset(registered_types, '\0', type_storage * sizeof(blueprint *)); | 327 memset(registered_types, '\0', type_storage * sizeof(blueprint *)); |
270 else | 328 else |
271 { | 329 { |
272 fprintf(stderr, "Couldn't allocate %d bytes for type storage array\n", type_storage * sizeof(blueprint *)); | 330 fprintf(stderr, "Couldn't allocate %d bytes for type storage array\n", type_storage * sizeof(blueprint *)); |
283 void normal_free(object * obj) | 341 void normal_free(object * obj) |
284 { | 342 { |
285 blueprint * bp = get_blueprint(obj); | 343 blueprint * bp = get_blueprint(obj); |
286 if(bp->cleanup) | 344 if(bp->cleanup) |
287 bp->cleanup(obj); | 345 bp->cleanup(obj); |
346 #ifndef USE_GC | |
288 ffree(obj, bp->boxed_size, manager); | 347 ffree(obj, bp->boxed_size, manager); |
348 #endif | |
289 } | 349 } |
290 | 350 |
291 void multi_free(object * obj) | 351 void multi_free(object * obj) |
292 { | 352 { |
293 multisize * multi = (multisize *)obj; | 353 multisize * multi = (multisize *)obj; |
294 blueprint * bp = get_blueprint(obj); | 354 blueprint * bp = get_blueprint(obj); |
295 if(bp->cleanup) | 355 if(bp->cleanup) |
296 bp->cleanup(obj); | 356 bp->cleanup(obj); |
357 #ifndef USE_GC | |
297 ffree(multi, sizeof(multisize) + multi->size, manager); | 358 ffree(multi, sizeof(multisize) + multi->size, manager); |
359 #endif | |
298 } | 360 } |
299 | 361 |
300 blueprint * new_blueprint(uint32_t type, int32_t size, special_func init, special_func copy, special_func cleanup) | 362 blueprint * new_blueprint(uint32_t type, int32_t size, special_func init, special_func copy, special_func cleanup) |
301 { | 363 { |
364 #ifdef USE_GC | |
365 blueprint * bp = GC_malloc(sizeof(blueprint)); | |
366 #else | |
302 blueprint * bp = malloc(sizeof(blueprint)); | 367 blueprint * bp = malloc(sizeof(blueprint)); |
368 | |
303 //dirty hack!, move elsewhere | 369 //dirty hack!, move elsewhere |
304 if (!manager) { | 370 if (!manager) { |
305 fixed_alloc_init(); | 371 fixed_alloc_init(); |
306 manager = new_mem_manager(); | 372 manager = new_mem_manager(); |
307 } | 373 } |
374 #endif | |
308 if(bp) | 375 if(bp) |
309 { | 376 { |
310 bp->size = size; | 377 bp->size = size; |
311 bp->boxed_size = size >= 0 ? size + sizeof(object) : 0; | 378 bp->boxed_size = size >= 0 ? size + sizeof(object) : 0; |
312 bp->method_lookup = bp->getter_lookup = bp->setter_lookup = bp->convert_to = bp->convert_from = NULL; | 379 bp->method_lookup = bp->getter_lookup = bp->setter_lookup = bp->convert_to = bp->convert_from = NULL; |
341 blueprint * register_type(int32_t size, special_func init, special_func copy, special_func cleanup) | 408 blueprint * register_type(int32_t size, special_func init, special_func copy, special_func cleanup) |
342 { | 409 { |
343 return register_type_byid(max_registered_type, size, init, copy, cleanup); | 410 return register_type_byid(max_registered_type, size, init, copy, cleanup); |
344 } | 411 } |
345 | 412 |
413 /* | |
346 void add_method(blueprint * bp, uint32_t methodid, rhope_func impl) | 414 void add_method(blueprint * bp, uint32_t methodid, rhope_func impl) |
347 { | 415 { |
348 rhope_func * temp; | 416 rhope_func * temp; |
349 if(methodid < 1) { | 417 if(methodid < 1) { |
350 fputs("Attempt to add a method with an ID < 1\n", stderr); | 418 fputs("Attempt to add a method with an ID < 1\n", stderr); |
487 bp->last_setfieldid = setfieldid+1; | 555 bp->last_setfieldid = setfieldid+1; |
488 } | 556 } |
489 } | 557 } |
490 bp->setter_lookup[setfieldid-bp->first_setfieldid] = impl; | 558 bp->setter_lookup[setfieldid-bp->first_setfieldid] = impl; |
491 } | 559 } |
560 */ | |
492 | 561 |
493 blueprint * get_blueprint_byid(uint32_t type) | 562 blueprint * get_blueprint_byid(uint32_t type) |
494 { | 563 { |
495 if(type >= max_registered_type) | 564 if(type >= max_registered_type) |
496 return NULL; | 565 return NULL; |