source: trunk/ab5.0/ablib/src/system/gc.sbp@ 560

Last change on this file since 560 was 546, checked in by dai, 16 years ago

VarPtr(This)をエラーとして扱うようにした。
・デリゲート生成時にThisに対するオブジェクトポインタが正常に取得できないバグを修正。
(※64bit版を後日対応すること)

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