00001
00013
00014 #ifdef HAVE_MEMORY_H
00015 #include <memory.h>
00016 #else
00017 #include <string.h>
00018 #endif
00019
00020
00021 #include "NewtGC.h"
00022 #include "NewtObj.h"
00023 #include "NewtMem.h"
00024 #include "NewtEnv.h"
00025 #include "NewtVM.h"
00026 #include "NewtIO.h"
00027 #include "NewtPrint.h"
00028
00029
00030
00031 static void NewtPoolSnap(const char * title, newtPool pool, int32_t usesize);
00032
00033 static void NewtObjChain(newtObjRef * objp, newtObjRef obj);
00034 static void NewtPoolChain(newtPool pool, newtObjRef obj, bool literal);
00035 static void NewtObjFree(newtPool pool, newtObjRef obj);
00036 static void NewtObjChainFree(newtPool pool, newtObjRef * objp);
00037
00038 #if 0
00039 static void NewtPoolMarkClean(newtPool pool);
00040 #endif
00041
00042 static void NewtPoolSweep(newtPool pool, bool mark);
00043
00044 static void NewtGCRefMark(newtRefArg r, bool mark);
00045 static void NewtGCRegMark(vm_reg_t * reg, bool mark);
00046 static void NewtGCStackMark(vm_env_t * env, bool mark);
00047 static void NewtGCMark(vm_env_t * env, bool mark);
00048
00049
00050 #pragma mark -
00051
00061 void NewtPoolSnap(const char * title, newtPool pool, int32_t usesize)
00062 {
00063 NewtDebugMsg(title, "mem = %d(%d)n", pool->usesize, pool->usesize - usesize);
00064 }
00065
00066
00067 #pragma mark -
00068
00079 void NewtObjChain(newtObjRef * objp, newtObjRef obj)
00080 {
00081 if (*objp == NULL)
00082 {
00083 *objp = obj;
00084 }
00085 else
00086 {
00087 obj->header.nextp = *objp;
00088 *objp = obj;
00089 }
00090 }
00091
00092
00093
00103 void NewtPoolChain(newtPool pool, newtObjRef obj, bool literal)
00104 {
00105 if (obj != NULL && pool != NULL)
00106 {
00107 if (literal)
00108 NewtObjChain(&pool->literal, obj);
00109 else
00110 NewtObjChain(&pool->obj, obj);
00111 }
00112 }
00113
00114
00115
00124 void NewtCheckGC(newtPool pool, size_t size)
00125 {
00126 if (pool->maxspace < pool->usesize + size)
00127 {
00128 NEWT_NEEDGC = true;
00129 }
00130 }
00131
00132
00133
00143 newtObjRef NewtObjChainAlloc(newtPool pool, size_t size, size_t dataSize)
00144 {
00145 newtObjRef obj;
00146
00147 NewtCheckGC(pool, size + dataSize);
00148
00149 obj = (newtObjRef)NewtMemAlloc(pool, size);
00150 if (obj == NULL) return NULL;
00151
00152 memset(&obj->header, 0, sizeof(obj->header));
00153
00154 if (0 < dataSize)
00155 {
00156 uint8_t * data;
00157
00158 data = NewtMemAlloc(pool, dataSize);
00159
00160 if (data == NULL)
00161 {
00162 NewtMemFree(obj);
00163 return NULL;
00164 }
00165
00166 *((uint8_t **)(obj + 1)) = data;
00167 }
00168 else
00169 {
00170 obj->header.h = kNewtObjLiteral;
00171 }
00172
00173 if (pool != NULL)
00174 {
00175 NewtPoolChain(pool, obj, dataSize == 0);
00176 pool->usesize += size + dataSize;
00177 }
00178
00179 return obj;
00180 }
00181
00182
00183 #pragma mark -
00184
00193 void NewtObjFree(newtPool pool, newtObjRef obj)
00194 {
00195 uint32_t datasize;
00196
00197 if (NewtObjIsLiteral(obj))
00198 {
00199 datasize = NewtAlign(sizeof(newtObj) + NewtObjSize(obj), 4);
00200 }
00201 else
00202 {
00203 datasize = sizeof(newtObj) + sizeof(uint8_t *);
00204 datasize += NewtObjCalcDataSize(NewtObjSize(obj));
00205
00206 NewtMemFree(NewtObjData(obj));
00207 }
00208
00209 NewtMemFree(obj);
00210
00211 if (pool != NULL)
00212 pool->usesize -= datasize;
00213 }
00214
00215
00216
00225 void NewtObjChainFree(newtPool pool, newtObjRef * objp)
00226 {
00227 newtObjRef nextp;
00228 newtObjRef obj;
00229
00230 for (obj = *objp; obj != NULL; obj = nextp)
00231 {
00232 nextp = obj->header.nextp;
00233 NewtObjFree(pool, obj);
00234 }
00235
00236 *objp = NULL;
00237 }
00238
00239
00240
00248 void NewtPoolRelease(newtPool pool)
00249 {
00250 if (pool != NULL)
00251 {
00252 int32_t usesize;
00253
00254 usesize = pool->usesize;
00255
00256 NewtObjChainFree(pool, &pool->obj);
00257 NewtObjChainFree(pool, &pool->literal);
00258
00259 if (NEWT_DEBUG)
00260 NewtPoolSnap("RELEASE", pool, usesize);
00261 }
00262 }
00263
00264
00265 #pragma mark -
00266 #if 0
00267
00275 void NewtPoolMarkClean(newtPool pool)
00276 {
00277 if (pool != NULL)
00278 {
00279 newtObjRef nextp;
00280 newtObjRef obj;
00281 newtObjRef * prevp = &pool->obj;
00282 int32_t usesize;
00283
00284 usesize = pool->usesize;
00285
00286 for (obj = pool->obj; obj != NULL; obj = nextp)
00287 {
00288 nextp = obj->header.nextp;
00289
00290 if (NewtObjIsLiteral(obj))
00291 {
00292 NewtObjChain(&pool->literal, obj);
00293 *prevp = nextp;
00294
00295 continue;
00296 }
00297
00298 obj->header.h &= (uint32_t)kNewtObjSweep;
00299 prevp = &obj->header.nextp;
00300 }
00301 }
00302 }
00303
00304 #endif
00305
00306
00315 void NewtPoolSweep(newtPool pool, bool mark)
00316 {
00317 if (pool != NULL)
00318 {
00319 newtObjRef nextp;
00320 newtObjRef obj;
00321 newtObjRef * prevp = &pool->obj;
00322 int32_t usesize;
00323
00324 usesize = pool->usesize;
00325
00326 for (obj = pool->obj; obj != NULL; obj = nextp)
00327 {
00328 nextp = obj->header.nextp;
00329
00330 if (NewtObjIsLiteral(obj))
00331 {
00332 NewtObjChain(&pool->literal, obj);
00333 *prevp = nextp;
00334
00335 continue;
00336 }
00337
00338 if (NewtObjIsSweep(obj, mark))
00339 {
00340 *prevp = nextp;
00341 NewtObjFree(pool, obj);
00342
00343 continue;
00344 }
00345
00346 prevp = &obj->header.nextp;
00347 }
00348
00349 if (NEWT_DEBUG)
00350 NewtPoolSnap("GC", pool, usesize);
00351 }
00352
00353 if (pool->maxspace < pool->usesize)
00354 {
00355 pool->maxspace = ((pool->usesize + pool->expandspace - 1) / pool->expandspace)
00356 * pool->expandspace;
00357 }
00358 }
00359
00360
00361
00370 void NewtGCRefMark(newtRefArg r, bool mark)
00371 {
00372 if (NewtRefIsPointer(r))
00373 {
00374 newtObjRef obj;
00375
00376 obj = NewtRefToPointer(r);
00377
00378 if (! NewtObjIsLiteral(obj) && NewtObjIsSweep(obj, mark))
00379 {
00380 if (mark)
00381 obj->header.h &= (uint32_t)kNewtObjSweep;
00382 else
00383 obj->header.h |= kNewtObjSweep;
00384
00385 if (NewtObjIsSlotted(obj))
00386 {
00387 newtRef * slots;
00388 uint32_t len;
00389 uint32_t i;
00390
00391 len = NewtObjSlotsLength(obj);
00392 slots = NewtObjToSlots(obj);
00393
00394 for (i = 0; i < len; i++)
00395 {
00396 NewtGCRefMark(slots[i], mark);
00397 }
00398 }
00399
00400 if (NewtObjIsFrame(obj))
00401 NewtGCRefMark(obj->as.map, mark);
00402 }
00403 }
00404 }
00405
00406
00407
00416 void NewtGCRegMark(vm_reg_t * reg, bool mark)
00417 {
00418 NewtGCRefMark(reg->func, mark);
00419 NewtGCRefMark(reg->locals, mark);
00420 NewtGCRefMark(reg->rcvr, mark);
00421 NewtGCRefMark(reg->impl, mark);
00422 }
00423
00424
00425
00434 void NewtGCStackMark(vm_env_t * env, bool mark)
00435 {
00436 newtRef * stack;
00437 vm_reg_t * callstack;
00438 uint32_t i;
00439
00440
00441 stack = (newtRef *)env->stack.stackp;
00442
00443 for (i = 0; i < env->reg.sp; i++)
00444 {
00445 NewtGCRefMark(stack[i], mark);
00446 }
00447
00448
00449 callstack = (vm_reg_t *)env->callstack.stackp;
00450
00451 for (i = 0; i < env->callstack.sp; i++)
00452 {
00453 NewtGCRegMark(&callstack[i], mark);
00454 }
00455
00456
00457 NewtGCRefMark(env->currexcp, mark);
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 }
00474
00475
00476
00485 void NewtGCMark(vm_env_t * env, bool mark)
00486 {
00487 NewtGCRefMark(NcGetRoot(), mark);
00488
00489
00490
00491
00492
00493 NewtGCRegMark(&env->reg, mark);
00494
00495
00496 NewtGCStackMark(env, mark);
00497 }
00498
00499
00500
00506 void NewtGC(void)
00507 {
00508
00509 NewtGCMark(&vm_env, NEWT_SWEEP);
00510 NewtPoolSweep(NEWT_POOL, NEWT_SWEEP);
00511
00512 NEWT_SWEEP = ! NEWT_SWEEP;
00513 NEWT_NEEDGC = false;
00514 }
00515
00516
00517 #pragma mark -
00518
00528 newtRef NsGC(newtRefArg rcvr)
00529 {
00530 NEWT_NEEDGC = true;
00531 return kNewtRefNIL;
00532 }
00533