root/NEWT0/trunk/src/newt_core/NewtGC.c

Revision 113, 11.9 kB (checked in by gnue, 17 months ago)

'#pragma mark' is invalidated by '#if 0'

Line 
1/*------------------------------------------------------------------------*/
2/**
3 * @file    NewtGC.c
4 * @brief   ガベージコレクション
5 *
6 * @author  M.Nukui
7 * @date    2003-11-07
8 *
9 * Copyright (C) 2003-2004 M.Nukui All rights reserved.
10 */
11
12
13/* ヘッダファイル */
14#ifdef HAVE_MEMORY_H
15    #include <memory.h>
16#else
17    #include <string.h>
18#endif
19
20
21#include "NewtGC.h"
22#include "NewtObj.h"
23#include "NewtMem.h"
24#include "NewtEnv.h"
25#include "NewtVM.h"
26#include "NewtIO.h"
27#include "NewtPrint.h"
28
29
30/* 関数プロトタイプ */
31static void     NewtPoolSnap(const char * title, newtPool pool, int32_t usesize);
32
33static void     NewtObjChain(newtObjRef * objp, newtObjRef obj);
34static void     NewtPoolChain(newtPool pool, newtObjRef obj, bool literal);
35static void     NewtObjFree(newtPool pool, newtObjRef obj);
36static void     NewtObjChainFree(newtPool pool, newtObjRef * objp);
37
38#if 0
39static void     NewtPoolMarkClean(newtPool pool);
40#endif
41
42static void     NewtPoolSweep(newtPool pool, bool mark);
43
44static void     NewtGCRefMark(newtRefArg r, bool mark);
45static void     NewtGCRegMark(vm_reg_t * reg, bool mark);
46static void     NewtGCStackMark(vm_env_t * env, bool mark);
47static void     NewtGCMark(vm_env_t * env, bool mark);
48
49
50#if 0
51#pragma mark -
52#endif
53/*------------------------------------------------------------------------*/
54/** メモリプールのスナップショットを出力する
55 *
56 * @param title     [in] タイトル
57 * @param pool      [in] メモリプール
58 * @param usesize   [in] GC前の使用サイズ
59 *
60 * @return          なし
61 */
62
63void NewtPoolSnap(const char * title, newtPool pool, int32_t usesize)
64{
65    NewtDebugMsg(title, "mem = %d(%d)\n", pool->usesize, pool->usesize - usesize);
66}
67
68
69#if 0
70#pragma mark -
71#endif
72/*------------------------------------------------------------------------*/
73/** オブジェクトデータをチェインする
74 *
75 * @param objp      [in] チェインされるオブジェクトデータへのポインタ
76 * @param obj       [in] チェインするオブジェクトデータ
77 *
78 * @return          なし
79 *
80 * @note            objp の参照先が NULL の場合は obj をセットして返す
81 */
82
83void NewtObjChain(newtObjRef * objp, newtObjRef obj)
84{
85    if (*objp == NULL)
86    {
87        *objp = obj;
88    }
89    else
90    {
91        obj->header.nextp = *objp;
92        *objp = obj;
93    }
94}
95
96
97/*------------------------------------------------------------------------*/
98/** メモリプール内でオブジェクトデータをチェインする
99 *
100 * @param pool      [in] メモリプール
101 * @param obj       [in] チェインするオブジェクトデータ
102 * @param literal   [in] リテラルかどうか
103 *
104 * @return          なし
105 */
106
107void NewtPoolChain(newtPool pool, newtObjRef obj, bool literal)
108{
109    if (obj != NULL && pool != NULL)
110    {
111        if (literal)
112            NewtObjChain(&pool->literal, obj);
113        else
114            NewtObjChain(&pool->obj, obj);
115    }
116}
117
118
119/*------------------------------------------------------------------------*/
120/** GCが必要かチェックする
121 *
122 * @param pool      [in] メモリプール
123 * @param size      [in] 追加サイズ
124 *
125 * @return          なし
126 */
127
128void NewtCheckGC(newtPool pool, size_t size)
129{
130    if (pool->maxspace < pool->usesize + size)
131    {
132        NEWT_NEEDGC = true;
133    }
134}
135
136
137/*------------------------------------------------------------------------*/
138/** メモリプール内でオブジェクトメモリを確保してチェインする
139 *
140 * @param pool      [in] メモリプール
141 * @param size      [in] オブジェクトサイズ
142 * @param dataSize  [in] データサイズ
143 *
144 * @return          オブジェクトデータ
145 */
146
147newtObjRef NewtObjChainAlloc(newtPool pool, size_t size, size_t dataSize)
148{
149    newtObjRef  obj;
150
151    NewtCheckGC(pool, size + dataSize);
152
153    obj = (newtObjRef)NewtMemAlloc(pool, size);
154    if (obj == NULL) return NULL;
155
156    memset(&obj->header, 0, sizeof(obj->header));
157
158    if (0 < dataSize)
159    {
160        uint8_t *   data;
161   
162        data = NewtMemAlloc(pool, dataSize);
163   
164        if (data == NULL)
165        {
166            NewtMemFree(obj);
167            return NULL;
168        }
169
170        *((uint8_t **)(obj + 1)) = data;
171    }
172    else
173    {
174        obj->header.h = kNewtObjLiteral;
175    }
176
177    if (pool != NULL)
178    {
179        NewtPoolChain(pool, obj, dataSize == 0);
180        pool->usesize += size + dataSize;
181    }
182
183    return obj;
184}
185
186
187#if 0
188#pragma mark -
189#endif
190/*------------------------------------------------------------------------*/
191/** オブジェクトを解放する
192 *
193 * @param pool      [in] メモリプール
194 * @param obj       [in] オブジェクト
195 *
196 * @return          なし
197 */
198
199void NewtObjFree(newtPool pool, newtObjRef obj)
200{
201    uint32_t    datasize;
202
203    if (NewtObjIsLiteral(obj))
204    {
205        datasize = NewtAlign(sizeof(newtObj) + NewtObjSize(obj), 4);
206    }
207    else
208    {
209        datasize = sizeof(newtObj) + sizeof(uint8_t *);
210        datasize += NewtObjCalcDataSize(NewtObjSize(obj));
211
212        NewtMemFree(NewtObjData(obj));
213    }
214
215    NewtMemFree(obj);
216
217    if (pool != NULL)
218        pool->usesize -= datasize;
219}
220
221
222/*------------------------------------------------------------------------*/
223/** オブジェクトデータにチェインされている全てのオブジェクトデータを解放する
224 *
225 * @param pool      [in] メモリプール
226 * @param objp      [i/o]オブジェクトデータへのポインタ
227 *
228 * @return          なし
229 */
230
231void NewtObjChainFree(newtPool pool, newtObjRef * objp)
232{
233    newtObjRef  nextp;
234    newtObjRef  obj;
235
236    for (obj = *objp; obj != NULL; obj = nextp)
237    {
238        nextp = obj->header.nextp;
239        NewtObjFree(pool, obj);
240    }
241
242    *objp = NULL;
243}
244
245
246/*------------------------------------------------------------------------*/
247/** メモリプールの解放
248 *
249 * @param pool      [in] メモリプール
250 *
251 * @return          なし
252 */
253
254void NewtPoolRelease(newtPool pool)
255{
256    if (pool != NULL)
257    {
258        int32_t     usesize;
259
260        usesize = pool->usesize;
261
262        NewtObjChainFree(pool, &pool->obj);
263        NewtObjChainFree(pool, &pool->literal);
264
265        if (NEWT_DEBUG)
266            NewtPoolSnap("RELEASE", pool, usesize);
267    }
268}
269
270
271#if 0
272#pragma mark -
273#endif
274
275#if 0
276/*------------------------------------------------------------------------*/
277/** オブジェクトのマークをクリアする
278 *
279 * @param pool      [in] メモリプール
280 *
281 * @return          なし
282 */
283
284void NewtPoolMarkClean(newtPool pool)
285{
286    if (pool != NULL)
287    {
288        newtObjRef  nextp;
289        newtObjRef  obj;
290        newtObjRef *    prevp = &pool->obj;
291        int32_t     usesize;
292
293        usesize = pool->usesize;
294
295        for (obj = pool->obj; obj != NULL; obj = nextp)
296        {
297            nextp = obj->header.nextp;
298
299            if (NewtObjIsLiteral(obj))
300            {
301                NewtObjChain(&pool->literal, obj);
302                *prevp = nextp;
303
304                continue;
305            }
306
307            obj->header.h &= ~ (uint32_t)kNewtObjSweep;
308            prevp = &obj->header.nextp;
309        }
310    }
311}
312
313#endif
314
315/*------------------------------------------------------------------------*/
316/** メモリプール内のオブジェクトをスウィープ(掃除)する
317 *
318 * @param pool      [in] メモリプール
319 * @param mark      [in] マークフラグ
320 *
321 * @return          なし
322 */
323
324void NewtPoolSweep(newtPool pool, bool mark)
325{
326    if (pool != NULL)
327    {
328        newtObjRef  nextp;
329        newtObjRef  obj;
330        newtObjRef *    prevp = &pool->obj;
331        int32_t     usesize;
332
333        usesize = pool->usesize;
334
335        for (obj = pool->obj; obj != NULL; obj = nextp)
336        {
337            nextp = obj->header.nextp;
338
339            if (NewtObjIsLiteral(obj))
340            {
341                NewtObjChain(&pool->literal, obj);
342                *prevp = nextp;
343
344                continue;
345            }
346
347            if (NewtObjIsSweep(obj, mark))
348            {
349                *prevp = nextp;
350                NewtObjFree(pool, obj);
351
352                continue;
353            }
354
355            prevp = &obj->header.nextp;
356        }
357
358        if (NEWT_DEBUG)
359            NewtPoolSnap("GC", pool, usesize);
360    }
361
362    if (pool->maxspace < pool->usesize)
363    {
364        pool->maxspace = ((pool->usesize + pool->expandspace - 1) / pool->expandspace)
365                            * pool->expandspace;
366    }
367}
368
369
370/*------------------------------------------------------------------------*/
371/** オブジェクトをマークする
372 *
373 * @param r         [in] オブジェクト
374 * @param mark      [in] マークフラグ
375 *
376 * @return          なし
377 */
378
379void NewtGCRefMark(newtRefArg r, bool mark)
380{
381    if (NewtRefIsPointer(r))
382    {
383        newtObjRef  obj;
384   
385        obj = NewtRefToPointer(r);
386   
387        if (! NewtObjIsLiteral(obj) && NewtObjIsSweep(obj, mark))
388        {
389            if (mark)
390                obj->header.h &= ~ (uint32_t)kNewtObjSweep;
391            else
392                obj->header.h |= kNewtObjSweep;
393
394            if (NewtObjIsSlotted(obj))
395            {
396                newtRef *   slots;
397                uint32_t    len;
398                uint32_t    i;
399   
400                len = NewtObjSlotsLength(obj);
401                slots = NewtObjToSlots(obj);
402   
403                for (i = 0; i < len; i++)
404                {
405                    NewtGCRefMark(slots[i], mark);
406                }
407            }
408   
409            if (NewtObjIsFrame(obj))
410                NewtGCRefMark(obj->as.map, mark);
411        }
412    }
413}
414
415
416/*------------------------------------------------------------------------*/
417/** レジスタ内のオブジェクトをマークする
418 *
419 * @param reg       [in] レジスタ
420 * @param mark      [in] マークフラグ
421 *
422 * @return          なし
423 */
424
425void NewtGCRegMark(vm_reg_t * reg, bool mark)
426{
427    NewtGCRefMark(reg->func, mark);
428    NewtGCRefMark(reg->locals, mark);
429    NewtGCRefMark(reg->rcvr, mark);
430    NewtGCRefMark(reg->impl, mark);
431}
432
433
434/*------------------------------------------------------------------------*/
435/** スタック内のオブジェクトをマークする
436 *
437 * @param env       [in] 実行環境
438 * @param mark      [in] マークフラグ
439 *
440 * @return          なし
441 */
442
443void NewtGCStackMark(vm_env_t * env, bool mark)
444{
445    newtRef *   stack;
446    vm_reg_t *  callstack;
447    uint32_t    i;
448
449    // スタック
450    stack = (newtRef *)env->stack.stackp;
451
452    for (i = 0; i < env->reg.sp; i++)
453    {
454        NewtGCRefMark(stack[i], mark);
455    }
456
457    // 関数呼出しスタック
458    callstack = (vm_reg_t *)env->callstack.stackp;
459
460    for (i = 0; i < env->callstack.sp; i++)
461    {
462        NewtGCRegMark(&callstack[i], mark);
463    }
464
465    // 例外ハンドラ・スタック
466    NewtGCRefMark(env->currexcp, mark);
467
468/*
469    {
470        vm_excp_t * excpstack;
471        vm_excp_t * excp;
472
473        excpstack = (vm_excp_t *)env->excpstack.stackp;
474
475        for (i = 0; i < env->excpsp; i++)
476        {
477            excp = &excpstack[i];
478            NewtGCRefMark(excp->sym, mark);
479        }
480    }
481*/
482}
483
484
485/*------------------------------------------------------------------------*/
486/** 参照されているオブジェクトをマークする
487 *
488 * @param env       [in] 実行環境
489 * @param mark      [in] マークフラグ
490 *
491 * @return          なし
492 */
493
494void NewtGCMark(vm_env_t * env, bool mark)
495{
496    NewtGCRefMark(NcGetRoot(), mark);
497//    NewtGCRefMark(NSGetGlobals(), mark);
498//    NewtGCRefMark(NSGetGlobalFns(), mark);
499//    NewtGCRefMark(NSGetMagicPointers(), mark);
500
501    // レジスタ
502    NewtGCRegMark(&env->reg, mark);
503
504    // スタック
505    NewtGCStackMark(env, mark);
506}
507
508
509/*------------------------------------------------------------------------*/
510/** ガベージコレクションの実行
511 *
512 * @return          なし
513 */
514
515void NewtGC(void)
516{
517//    NewtPoolMarkClean(NEWT_POOL);
518    vm_env_t *  env;
519
520    for (env = &vm_env; env; env = env->next)
521    {
522        NewtGCMark(&vm_env, NEWT_SWEEP);
523    }
524
525    NewtPoolSweep(NEWT_POOL, NEWT_SWEEP);
526
527    NEWT_SWEEP = ! NEWT_SWEEP;
528    NEWT_NEEDGC = false;
529}
530
531
532#if 0
533#pragma mark -
534#endif
535/*------------------------------------------------------------------------*/
536/** スクリプトから GC を呼出す(実際には GC を予約するだけ)
537 *
538 * @param rcvr      [in] レシーバ
539 *
540 * @return          NIL
541 *
542 * @note            スクリプトからの呼出し用
543 */
544
545newtRef NsGC(newtRefArg rcvr)
546{
547    NEWT_NEEDGC = true;
548    return kNewtRefNIL;
549}
Note: See TracBrowser for help on using the browser.