source: trunk/Include/system/gc.sbp@ 368

Last change on this file since 368 was 368, checked in by dai, 17 years ago

GCのマーク時間を短縮した

File size: 19.9 KB
RevLine 
[360]1/*!
2 @brief このファイルでは、ABのガベージコレクションの実装を行います。
[109]3*/
[1]4
[109]5
[1]6/*
7※これらの変数はコンパイラが自動的に定義します。
8Dim _System_gc_StackRoot_StartPtr As VoidPtr
9*/
10
11Function _System_GetSp() As LONG_PTR 'dummy
12End Function
13
14
15Const _System_GC_FLAG_ATOMIC = 1
16Const _System_GC_FLAG_NEEDFREE = 2
17Const _System_GC_FLAG_INITZERO = 4
[144]18Const _System_GC_FLAG_OBJECT = 8
[1]19
[214]20Type _System_GlobalRoot
21 ptr As *LONG_PTR
22 count As Long
23End Type
24
[361]25Type _System_MemoryObject
26 ptr As VoidPtr
27 size As Long
28 flags As DWord
29 generationCount As Long
30End Type
31
[1]32Class _System_CGarbageCollection
[266]33
[361]34 pMemoryObjects As *_System_MemoryObject ' メモリオブジェクト
35 countOfMemoryObjects As Long ' 管理するメモリオブジェクトの個数
[1]36
37 iAllSize As SIZE_T
38
[360]39 isSweeping As Boolean ' スウィープ中かどうか
[144]40
[360]41 ' クリティカルセクション
[1]42 CriticalSection As CRITICAL_SECTION
43
[214]44 ' メモリの上限値(この値を超えるとGCが発動します)
45 limitMemorySize As LONG_PTR ' バイト単位
46 limitMemoryObjectNum As Long ' メモリオブジェクトの個数単位
[109]47
[360]48 isFinish As Boolean ' GC管理が終了したかどうか
[144]49
50
[214]51 ' Global Root
52 pGlobalRoots As *_System_GlobalRoot
53 globalRootNum As Long
54 Sub AddGlobalRootPtr( ptr As *LONG_PTR, count As Long )
55 pGlobalRoots = _System_realloc( pGlobalRoots, (globalRootNum + 1) * SizeOf(_System_GlobalRoot) )
56 pGlobalRoots[globalRootNum].ptr = ptr
57 pGlobalRoots[globalRootNum].count = count
58 globalRootNum++
59 End Sub
60
61 Sub RegisterGlobalRoots()
62 ' このメソッドの実装はコンパイラが自動生成する
63
64 ' AddGlobalRootPtr(...)
65 ' ...
66 End Sub
67
[144]68 ' 特殊クラスのため、コンストラクタ・デストラクタは呼ばれません
[1]69 Sub _System_CGarbageCollection()
[144]70 End Sub
71 Sub ~_System_CGarbageCollection()
72 End Sub
73
[214]74Public
75
[360]76 /*!
77 @brief 環境変数にGCを登録する
78 @author Daisuke Yamamoto
79 @date 2007/10/21
80 */
[266]81 Static Sub Initialize()
82 Dim temporary[255] As Char
83 If GetEnvironmentVariable( "ActiveBasicGarbageCollection", temporary, 255 ) Then
84 ' 既にGCがプロセスに存在するとき
[364]85 _stscanf( temporary, "%08x", VarPtr( _System_pGC ) )
[266]86 MessageBox(0,temporary,"GetEnvironmentVariable",0)
87 Else
88 _System_pGC = _System_calloc( SizeOf( _System_CGarbageCollection ) )
89 _System_pGC->Begin()
90
91 ' GCをプロセスに登録する
[364]92 _stprintf( temporary, "%08x", _System_pGC )
[266]93 SetEnvironmentVariable( "ActiveBasicGarbageCollection", temporary )
94 End If
95 End Sub
96
[360]97 /*!
98 @brief メモリサイズの上限を指定する
99 @param limitMemorySize メモリサイズの上限(単位はバイト)
100 limitMemoryObjectNum メモリ個数の上限
101 @author Daisuke Yamamoto
102 @date 2007/10/21
103 */
104 Sub SetLimit( limitMemorySize As LONG_PTR, limitMemoryObjectNum As Long )
105 This.limitMemorySize = limitMemorySize
106 This.limitMemoryObjectNum = limitMemoryObjectNum
107 End Sub
108
109 /*!
110 @brief 初期化
111 @author Daisuke Yamamoto
112 @date 2007/10/21
113 */
[144]114 Sub Begin()
[361]115 If pMemoryObjects Then Exit Sub
[1]116
[144]117 isFinish = False
118
119 'メモリの上限値(この値を超えるとGCが発動します)
[362]120 SetLimit(
121 1024*1024, ' バイト単位
122 2000 ' メモリオブジェクトの個数単位
123 )
[144]124
[361]125 pMemoryObjects = _System_calloc( 1 )
126 countOfMemoryObjects=0
[1]127
[214]128 ' Global Root
129 pGlobalRoots = _System_calloc( 1 )
130 globalRootNum = 0
131 RegisterGlobalRoots()
132
[1]133 iAllSize=0
134
[144]135 ' スウィープ中かどうか
136 isSweeping = False
[1]137
138 'クリティカルセッションを生成
139 InitializeCriticalSection(CriticalSection)
140
[18]141
142 '---------------------------
143 ' 開始時のスレッドを通知
144 '---------------------------
[1]145 Dim hTargetThread As HANDLE
146 DuplicateHandle(GetCurrentProcess(),
147 GetCurrentThread(),
148 GetCurrentProcess(),
149 hTargetThread, 0, FALSE, DUPLICATE_SAME_ACCESS) 'カレントスレッドのハンドルを複製
[18]150
[144]151 ' スレッド管理用オブジェクトを生成
152 _System_pobj_AllThreads = New _System_CThreadCollection()
[18]153
[144]154 ' 自身のThreadオブジェクトを生成
155 Dim thread As Thread(hTargetThread,GetCurrentThreadId(),0)
[330]156 thread.Name = "main"
[18]157
[232]158 _System_pobj_AllThreads->BeginThread(ObjPtr( thread ),_System_gc_StackRoot_StartPtr As *LONG_PTR)
[144]159
[1]160 End Sub
[360]161
162 /*!
163 @brief 終了処理
164 @author Daisuke Yamamoto
165 @date 2007/10/21
166 */
[144]167 Sub Finish()
[361]168 If pMemoryObjects = NULL Then Exit Sub
[1]169
[144]170 isFinish = True
[79]171
[144]172 ' スレッド管理用オブジェクトを破棄
173 Delete _System_pobj_AllThreads
[1]174
[144]175 ' 自分以外のスレッドを一時停止
176 '_System_pobj_AllThreads->SuspendAnotherThread()
177
[259]178 _System_DebugOnly_OutputDebugString( Ex"garbage colletion sweeping all memory objects!\r\n" )
[144]179 DeleteAllGarbageMemories()
180
181 ' 未解放のメモリオブジェクトをトレース
182 DumpMemoryLeaks()
183
184 ' 自分以外のスレッドを再開
185 '_System_pobj_AllThreads->ResumeAnotherThread()
186
[361]187 _System_free( pMemoryObjects )
188 pMemoryObjects = NULL
[1]189
[214]190 _System_free( pGlobalRoots )
191 pGlobalRoots = NULL
192
[1]193 'クリティカルセッションを破棄
194 DeleteCriticalSection(CriticalSection)
[144]195
[79]196 End Sub
[1]197
[360]198 /*!
[361]199 @brief メモリオブジェクトからインデックスを取得する
200 @param new_ptr メモリオブジェクトへのポインタ
201 @author Daisuke Yamamoto
202 @date 2007/10/21
203 */
204 Function GetMemoryObjectPtr( ptr As VoidPtr ) As *_System_MemoryObject
205 ' メモリオブジェクトの先頭部分からインデックスを取得する
206 Dim index = Get_LONG_PTR( ptr - SizeOf(LONG_PTR) ) As Long
207
208 If pMemoryObjects[index].ptr <> ptr Then
209 ' メモリイメージが壊れている(先頭に存在するインデックスの整合性が取れない)
210 Dim temporary[1024] As Char
[364]211#ifdef _WIN64
212 'wsprintfでは、Windows 2000以降でしか%pが使えない。
213 wsprintf( temporary, Ex"indexOfMemoryObjects: %d\r\npMemoryObjects[index].ptr: &H%p\r\nptr: &H%p\r\n",
214 index,
215 pMemoryObjects[index].ptr,
216 ptr )
217#else
[361]218 wsprintf( temporary, Ex"indexOfMemoryObjects: %d\r\npMemoryObjects[index].ptr: &H%08x\r\nptr: &H%08x\r\n",
219 index,
220 pMemoryObjects[index].ptr,
221 ptr )
[364]222#endif
[361]223 _System_DebugOnly_OutputDebugString( temporary )
224 debug
225 End If
226
227 Return VarPtr( pMemoryObjects[index] )
228 End Function
229
230 /*!
[360]231 @brief メモリオブジェクトを追加する
232 @param new_ptr メモリオブジェクトへのポインタ
233 size メモリオブジェクトのサイズ
234 flags メモリオブジェクトの属性
235 @author Daisuke Yamamoto
236 @date 2007/10/21
237 */
[170]238 Sub add(new_ptr As VoidPtr, size As SIZE_T, flags As DWord)
[144]239 EnterCriticalSection(CriticalSection)
[361]240 iAllSize+=size
[1]241
[361]242 ' メモリオブジェクトインスタンスの先頭にインデックスをセットする
243 Set_LONG_PTR( new_ptr - SizeOf( LONG_PTR ), countOfMemoryObjects )
[1]244
[361]245 pMemoryObjects = _System_realloc( pMemoryObjects, (countOfMemoryObjects+1)*SizeOf(_System_MemoryObject) )
246 pMemoryObjects[countOfMemoryObjects].ptr = new_ptr
247 pMemoryObjects[countOfMemoryObjects].size = size
248 pMemoryObjects[countOfMemoryObjects].flags = flags
249 pMemoryObjects[countOfMemoryObjects].generationCount = 0
[360]250
[361]251 countOfMemoryObjects++
[144]252 LeaveCriticalSection(CriticalSection)
[1]253
[330]254 /*
255 ' デバッグ用
[361]256 If countOfMemoryObjects = 1996 Then
[330]257 debug
258 End If
259 */
[1]260 End Sub
261
262
[360]263 /*!
264 @brief メモリオブジェクトを確保する
265 @param size メモリオブジェクトのサイズ
266 flags メモリオブジェクトの属性
267 @author Daisuke Yamamoto
268 @date 2007/10/21
269 */
[1]270 Function __malloc(size As SIZE_T,flags As Byte) As VoidPtr
[361]271 Dim dwFlags As DWord
272 If flags and _System_GC_FLAG_INITZERO Then
273 dwFlags=HEAP_ZERO_MEMORY
274 Else
275 dwFlags=0
276 End If
[1]277
[361]278 ' 実際のメモリバッファはインデックスの分だけ多めに確保する
279 Dim ptr = HeapAlloc( _System_hProcessHeap, dwFlags, size + SizeOf( LONG_PTR ) ) + SizeOf( LONG_PTR )
[1]280
[361]281 ' 管理対象のメモリオブジェクトとして追加
282 add( ptr, size, flags )
283
[144]284 Return ptr
[1]285 End Function
286
[360]287 /*!
288 @brief メモリオブジェクトを再確保する
289 @param lpMem メモリオブジェクトへのポインタ
290 size メモリオブジェクトのサイズ
291 flags メモリオブジェクトの属性
292 @author Daisuke Yamamoto
293 @date 2007/10/21
294 */
[1]295 Function __realloc(lpMem As VoidPtr, size As SIZE_T) As VoidPtr
[18]296 EnterCriticalSection(CriticalSection)
[1]297
[361]298 ' メモリオブジェクトを取得
299 Dim pTempMemoryObject = GetMemoryObjectPtr( lpMem )
[18]300
[361]301 iAllSize += size - pTempMemoryObject->size
302
303 pTempMemoryObject->size = size
304 pTempMemoryObject->ptr = HeapReAlloc( _System_hProcessHeap, HEAP_ZERO_MEMORY, pTempMemoryObject->ptr - SizeOf(LONG_PTR), size + SizeOf(LONG_PTR) ) + SizeOf(LONG_PTR)
305
[18]306 LeaveCriticalSection(CriticalSection)
[361]307 Return pTempMemoryObject->ptr
[1]308 End Function
309
[360]310 /*!
311 @brief メモリオブジェクトを解放する
312 @param lpMem メモリオブジェクトへのポインタ
313 isSweeping スウィープ中にこのメソッドが呼ばれるときはTrue、それ以外はFalse
314 @author Daisuke Yamamoto
315 @date 2007/10/21
316 */
[144]317 Sub __free_ex(lpMem As VoidPtr, isSweeping As Boolean)
[18]318 EnterCriticalSection(CriticalSection)
[1]319
[361]320 ' メモリオブジェクトを取得
321 Dim pTempMemoryObject = GetMemoryObjectPtr( lpMem )
322
323 If (pTempMemoryObject->flags and _System_GC_FLAG_NEEDFREE)<>0 or isSweeping Then
324 iAllSize -= pTempMemoryObject->size
325
326 HeapFree( _System_hProcessHeap, 0, pTempMemoryObject->ptr - SizeOf(LONG_PTR) )
327 pTempMemoryObject->ptr = NULL
328 pTempMemoryObject->size = 0
329 Else
330 If isFinish = False Then
331 _System_DebugOnly_OutputDebugString( Ex"heap free missing!\r\n" )
[1]332 End If
[361]333 End If
[18]334 LeaveCriticalSection(CriticalSection)
[1]335 End Sub
336
[360]337 /*!
338 @brief メモリオブジェクトを解放する
339 @param lpMem メモリオブジェクトへのポインタ
340 @author Daisuke Yamamoto
341 @date 2007/10/21
342 */
[144]343 Sub __free(lpMem As VoidPtr)
344 __free_ex( lpMem, False )
345 End Sub
346
[360]347 /*!
[368]348 @brief 必要であればスウィープする
[360]349 @author Daisuke Yamamoto
350 @date 2007/10/21
351 */
[368]352 Sub TrySweep()
[361]353 If isSweeping <> False or (iAllSize<limitMemorySize and countOfMemoryObjects<limitMemoryObjectNum) Then
[171]354 'メモリ使用量が上限値を超えていないとき
355 Exit Sub
356 End If
[144]357
[368]358 Sweep()
359 End Sub
360
361 /*!
362 @brief スウィープする
363 @author Daisuke Yamamoto
364 @date 2007/10/21
365 */
366 Sub Sweep()
[171]367 Dim hThread As HANDLE
368 Dim ThreadId As DWord
369 hThread=_beginthreadex(NULL,0,AddressOf(SweepOnOtherThread),VarPtr(This),0,ThreadId)
370 WaitForSingleObject(hThread,INFINITE)
371 CloseHandle(hThread)
[202]372 isSweeping = False
[1]373 End Sub
374
[144]375Private
[1]376
[214]377 Static Function IsNull( object As Object ) As Boolean
[237]378 Return Object.ReferenceEquals(object, Nothing)
[214]379 End Function
380
[360]381 /*!
382 @brief メモリオブジェクトの生存検地
383 @param pSample メモリオブジェクトへのポインタ
384 @author Daisuke Yamamoto
385 @date 2007/10/21
386 */
[144]387 Function HitTest(pSample As VoidPtr) As Long
[368]388 If pSample = NULL Then
389 Return -1
390 End If
391
[144]392 Dim i As Long
[361]393 For i=0 To ELM(countOfMemoryObjects)
394 If (pMemoryObjects[i].ptr As LONG_PTR)<=(pSample As LONG_PTR) and (pSample As LONG_PTR)<((pMemoryObjects[i].ptr As LONG_PTR)+pMemoryObjects[i].size) Then
[144]395 Return i
396 End If
397 Next
398 Return -1
399 End Function
[1]400
[360]401 /*!
402 @brief オブジェクトのスキャン
403 @param pObject オブジェクトへのポインタ
404 pbMark マークリスト
405 @author Daisuke Yamamoto
406 @date 2007/10/21
407 */
[214]408 Function ScanObject(pObject As *Object, pbMark As *Byte) As Boolean
[275]409 Dim classTypeInfo = Nothing As ActiveBasic.Core._System_TypeForClass
410 classTypeInfo = pObject->GetType() As ActiveBasic.Core._System_TypeForClass
[214]411
412 If IsNull( classTypeInfo ) Then
413 Return False
414 End If
415
[330]416 /*
417 _System_DebugOnly_OutputDebugString( " (scanning object)" )
418 _System_DebugOnly_OutputDebugString( classTypeInfo.Name )
419 _System_DebugOnly_OutputDebugString( Ex"\r\n" )
420 */
421
[214]422 Dim i As Long
423 For i = 0 To ELM(classTypeInfo.numOfReference)
424 Scan( (pObject + classTypeInfo.referenceOffsets[i]) As *LONG_PTR, 1, pbMark )
425 Next
426
427 Return True
428 End Function
429
[360]430 /*!
431 @brief メモリオブジェクトのスキャン
432 @param pStartPtr メモリオブジェクトへのポインタ
433 maxNum スキャンするメモリオブジェクトの個数
434 pbMark マークリスト
435 @author Daisuke Yamamoto
436 @date 2007/10/21
437 */
[214]438 Sub Scan(pStartPtr As *LONG_PTR, maxNum As Long, pbMark As *Byte)
439 Dim i As Long, index As Long
440
441 For i=0 To ELM(maxNum)
[144]442 index=HitTest(pStartPtr[i] As VoidPtr)
443 If index<>-1 Then
444 If pbMark[index]=0 Then
445 pbMark[index]=1
[170]446
[361]447 ' ジェネレーションカウントを増やす
448 pMemoryObjects[index].generationCount ++
449
450 If pMemoryObjects[index].flags and _System_GC_FLAG_OBJECT Then
[214]451 ' オブジェクトの場合
[361]452 If ScanObject( (pMemoryObjects[index].ptr + 4*SizeOf(LONG_PTR)) As *Object, pbMark) = False Then
453 Dim maxNum = (pMemoryObjects[index].size\SizeOf(LONG_PTR)) As Long
454 Scan(pMemoryObjects[index].ptr As *LONG_PTR, maxNum, pbMark)
[214]455 End If
456
[361]457 ElseIf (pMemoryObjects[index].flags and _System_GC_FLAG_ATOMIC)=0 Then
[214]458 ' ヒープ領域がポインタ値を含む可能性があるとき
[361]459 If pMemoryObjects[index].ptr = NULL Then
[144]460 'エラー
[170]461
[144]462 End If
[214]463
[361]464 Dim maxNum = (pMemoryObjects[index].size\SizeOf(LONG_PTR)) As Long
465 Scan(pMemoryObjects[index].ptr As *LONG_PTR, maxNum, pbMark)
[144]466 End If
467 End If
468 End If
469 Next
470 End Sub
[1]471
[360]472 /*!
473 @brief グローバル領域をルートに指定してスキャン
474 @param pbMark マークリスト
475 @author Daisuke Yamamoto
476 @date 2007/10/21
477 */
478 Sub GlobalScan( pbMark As *Byte )
479 Dim i As Long
480 For i = 0 To ELM( globalRootNum )
481 Scan( pGlobalRoots[i].ptr, pGlobalRoots[i].count, pbMark )
482 Next
483 End Sub
484
485 /*!
486 @brief ローカル領域をルートに指定してスキャン
487 @param pbMark マークリスト
488 @author Daisuke Yamamoto
489 @date 2007/10/21
490 */
[144]491 Sub LocalScan( pbMark As *Byte )
[18]492 Dim Context As CONTEXT
[1]493 Dim NowSp As *LONG_PTR
494 Dim size As LONG_PTR
[18]495 Dim i As Long
496 For i=0 To ELM(_System_pobj_AllThreads->ThreadNum)
[330]497 Dim thread = _System_pobj_AllThreads->ppobj_Thread[i]
498 If thread Then
[1]499 FillMemory(VarPtr(Context),SizeOf(CONTEXT),0)
500 Context.ContextFlags=CONTEXT_CONTROL
[330]501 If thread->__GetContext(Context)=0 Then
[259]502 _System_DebugOnly_OutputDebugString(Ex"レジスタ情報の取得に失敗しました。\r\n")
[1]503 End If
504
505#ifdef _WIN64
506 NowSp=Context.Rsp As *LONG_PTR
507#else
508 NowSp=Context.Esp As *LONG_PTR
509#endif
510
[214]511 Dim size=(_System_pobj_AllThreads->pStackBase[i] As LONG_PTR)-(NowSp As LONG_PTR)
512 Dim maxNum = (size\SizeOf(LONG_PTR)) As Long
[1]513
[144]514 If NowSp = 0 Then
515 debug
516 Exit Sub
517 End If
518
[330]519 /*
520 _System_DebugOnly_OutputDebugString( "(scanning thread local)" )
521 _System_DebugOnly_OutputDebugString( thread.Name )
522 _System_DebugOnly_OutputDebugString( Ex"\r\n" )
523 */
524
[214]525 Scan( NowSp, maxNum, pbMark )
[1]526 End If
527 Next
[144]528 End Sub
[1]529
[360]530 /*!
531 @brief 生存していないメモリオブジェクトを解放する
532 @param pbMark マークリスト
533 @author Daisuke Yamamoto
534 @date 2007/10/21
535 */
[144]536 Sub DeleteGarbageMemories( pbMark As *Byte )
[1]537
[144]538 Dim isAllDelete = False
539 If pbMark = NULL Then
540 ' すべてを破棄するとき
541 isAllDelete = True
[361]542 pbMark = _System_calloc( countOfMemoryObjects )
[144]543 End If
[1]544
[144]545 Dim i As Long
[361]546 For i=0 To ELM(countOfMemoryObjects)
547 If pbMark[i]=0 and pMemoryObjects[i].ptr<>0 and (pMemoryObjects[i].flags and _System_GC_FLAG_NEEDFREE)=0 Then
548 If pMemoryObjects[i].ptr = NULL Then
[144]549 If isAllDelete Then
550 Continue
551 Else
552 debug
553 End If
554 End If
[1]555
[361]556 Dim ptr = pMemoryObjects[i].ptr
557 Dim size = pMemoryObjects[i].size
[144]558
[361]559 If (pMemoryObjects[i].flags and _System_GC_FLAG_OBJECT) <> 0 Then
[144]560 /* ・オブジェクトの個数
561 ・オブジェクトのサイズ
562 ・デストラクタの関数ポインタ
[249]563 ・リザーブ領域
[144]564 を考慮 */
[249]565 _System_SweepingDelete (ptr + SizeOf( LONG_PTR ) * 4 )
[144]566 Else
[361]567 __free_ex( ptr, True )
[144]568 End If
[1]569 End If
570 Next
571
[144]572 If isAllDelete Then
573 _System_free( pbMark )
574 End If
575
576 End Sub
577
[360]578 /*!
579 @brief GCが管理するすべてのメモリオブジェクトを解放する
580 @author Daisuke Yamamoto
581 @date 2007/10/21
582 */
[144]583 Sub DeleteAllGarbageMemories()
584 DeleteGarbageMemories( NULL )
585 End Sub
586
[360]587 /*!
588 @brief コンパクション
589 @author Daisuke Yamamoto
590 @date 2007/10/21
591 */
[144]592 Sub Compaction()
593 Dim i As Long, i2 = 0 As Long
[361]594 For i=0 To ELM(countOfMemoryObjects)
595 pMemoryObjects[i2] = pMemoryObjects[i]
[144]596
[361]597 If pMemoryObjects[i2].ptr Then
598 ' メモリオブジェクトの先頭部分にあるインデックスを書き換える
599 Set_LONG_PTR( pMemoryObjects[i2].ptr - SizeOf(LONG_PTR), i2 )
600
[144]601 i2++
602 End If
603 Next
[361]604 countOfMemoryObjects = i2
[144]605 End Sub
606
[360]607 /*!
608 @brief スウィープ(新規スレッドで呼び出す必要あり)
609 @author Daisuke Yamamoto
610 @date 2007/10/21
611 */
[284]612 Function SweepOnOtherThread() As Long
[171]613 EnterCriticalSection(CriticalSection)
[144]614
[214]615
616 Dim startTime = GetTickCount()
617
[259]618 _System_DebugOnly_OutputDebugString( Ex"garbage colletion sweep start!\r\n" )
[214]619
620
[368]621 'If isSweeping <> False or (iAllSize<limitMemorySize and countOfMemoryObjects<limitMemoryObjectNum) Then
622 ' ExitThread(0)
623 'End If
[203]624 isSweeping = True
[202]625
[144]626 ' すべてのスレッドを一時停止
627 _System_pobj_AllThreads->SuspendAllThread()
628
629 ' マークリストを生成
[361]630 Dim pbMark = HeapAlloc(_System_hProcessHeap,HEAP_ZERO_MEMORY,countOfMemoryObjects*SizeOf(Byte)) As *Byte
[144]631
632 ' グローバル領域をルートに指定してスキャン
[360]633 GlobalScan( pbMark )
[144]634
635 ' ローカル領域をルートに指定してスキャン
636 LocalScan( pbMark )
637
638 ' スウィープ前のメモリサイズを退避
639 Dim iBackAllSize = iAllSize
640
641 ' スウィープ前のメモリオブジェクトの数
[361]642 Dim iBeforeN = countOfMemoryObjects
[144]643
644 '使われていないメモリを解放する
645 DeleteGarbageMemories(pbMark)
646
647 'コンパクション
648 Compaction()
649
[1]650 'マークリストを解放
651 HeapFree(_System_hProcessHeap,0,pbMark)
652
[299]653 If iBackAllSize <= iAllSize * 2 Then
[144]654 If iAllSize > limitMemorySize Then
655 limitMemorySize = iAllSize
656 End If
657
[1]658 '許容量を拡張する
[144]659 limitMemorySize *= 2
[214]660 limitMemoryObjectNum *= 2
[144]661
[259]662 _System_DebugOnly_OutputDebugString( Ex"memory size is extended for gc!\r\n" )
[1]663 End If
664
[144]665 Dim temp[100] As Char
[361]666 wsprintf(temp,Ex"object items ... %d -> %d ( %d MB -> %d MB )\r\n",iBeforeN,countOfMemoryObjects, iBackAllSize\1024\1024, iAllSize\1024\1024)
[259]667 _System_DebugOnly_OutputDebugString( temp )
[144]668 wsprintf(temp,Ex"limit size of memory ... %d\r\n",limitMemorySize)
[259]669 _System_DebugOnly_OutputDebugString( temp )
[214]670 wsprintf(temp,Ex"garbage colletion sweep finish! (%d ms)\r\n\r\n", GetTickCount()-startTime)
[259]671 _System_DebugOnly_OutputDebugString( temp )
[1]672
[144]673
[1]674 '-------------------------------------
675 ' すべてのスレッドを再開
676 '-------------------------------------
[18]677 _System_pobj_AllThreads->ResumeAllThread()
[171]678
679 LeaveCriticalSection(CriticalSection)
[1]680 End Function
681
[360]682 /*!
683 @brief 未解放のメモリオブジェクトをデバッグ出力する
684 @author Daisuke Yamamoto
685 @date 2007/10/21
686 */
[144]687 Sub DumpMemoryLeaks()
688 Dim isLeak = False
[1]689 Dim i As Long
[361]690 For i=0 To ELM(countOfMemoryObjects)
691 If pMemoryObjects[i].ptr Then
692 If (pMemoryObjects[i].flags and _System_GC_FLAG_NEEDFREE)<>0 Then
[144]693 If isLeak = False Then
[259]694 _System_DebugOnly_OutputDebugString( Ex"Detected memory leaks!\r\n" )
[144]695 isLeak = True
696 End If
[1]697
[144]698 Dim temp[100] As Char
[259]699 _System_DebugOnly_OutputDebugString( Ex"heap free missing!\r\n" )
[364]700#ifdef _WIN64
701 wsprintf(temp,Ex"{%d} normal block at &H%p, %d bytes long.\r\n", i, pMemoryObjects[i].ptr, pMemoryObjects[i].size)
702#else
[361]703 wsprintf(temp,Ex"{%d} normal block at &H%08X, %d bytes long.\r\n", i, pMemoryObjects[i].ptr, pMemoryObjects[i].size)
[364]704#endif
[259]705 _System_DebugOnly_OutputDebugString( temp )
[1]706 End If
707 End If
708 Next
[144]709
710 If isLeak Then
[259]711 _System_DebugOnly_OutputDebugString( Ex"Object dump complete.\r\n" )
[144]712 End If
[170]713
[1]714 End Sub
[144]715
[1]716End Class
717
718'GC管理用の特殊なシステムオブジェクト(デストラクタは最終のタイミングで呼び出されます)
[144]719Dim _System_pGC As *_System_CGarbageCollection
[1]720
721
722
723Function GC_malloc(size As Long) As VoidPtr
724 ' sweep
[368]725 _System_pGC->TrySweep()
[1]726
727 'allocate
[144]728 Return _System_pGC->__malloc(size,0)
[1]729End Function
730
731Function GC_malloc_atomic(size As Long) As VoidPtr
732 ' sweep
[368]733 _System_pGC->TrySweep()
[1]734
735 'allocate
[144]736 Return _System_pGC->__malloc(size,_System_GC_FLAG_ATOMIC)
[1]737End Function
[144]738
739Function _System_GC_malloc_ForObject(size As Long) As VoidPtr
740 ' sweep
[368]741 _System_pGC->TrySweep()
[144]742
743 'allocate
744 Return _System_pGC->__malloc(size,_System_GC_FLAG_OBJECT or _System_GC_FLAG_INITZERO)
745End Function
746
747Function _System_GC_malloc_ForObjectPtr(size As Long) As VoidPtr
748 ' sweep
[368]749 _System_pGC->TrySweep()
[144]750
751 'allocate
752 Return _System_pGC->__malloc(size,_System_GC_FLAG_OBJECT or _System_GC_FLAG_INITZERO or _System_GC_FLAG_NEEDFREE)
753End Function
754
755Function _System_GC_free_for_SweepingDelete( ptr As *Object )
756 ' free
757 _System_pGC->__free_ex( ptr, True )
758End Function
Note: See TracBrowser for help on using the repository browser.