source: Include/system/gc.sbp@ 137

Last change on this file since 137 was 109, checked in by dai, 18 years ago

_System_SWEEP_LIMIT_MEMORYをグローバル変数から静的メンバに変更した。

File size: 8.4 KB
Line 
1/*
2 このファイルでは、ABのガベージコレクションの実装を行います。
3*/
4
5
6/*
7※これらの変数はコンパイラが自動的に定義します。
8Dim _System_gc_GlobalRoot_StartPtr As VoidPtr
9Dim _System_gc_GlobalRoot_Size As Long
10Dim _System_gc_StackRoot_StartPtr As VoidPtr
11*/
12
13Function _System_GetSp() As LONG_PTR 'dummy
14End Function
15
16
17Const _System_GC_FLAG_ATOMIC = 1
18Const _System_GC_FLAG_NEEDFREE = 2
19Const _System_GC_FLAG_INITZERO = 4
20
21Const THREAD_GET_CONTEXT = &H0008
22
23Class _System_CGarbageCollection
24 ppPtr As **VoidPtr
25 pSize As *SIZE_T
26 pbFlags As *Byte
27 n As Long
28
29 iAllSize As SIZE_T
30
31 CriticalSection As CRITICAL_SECTION
32
33 'メモリの上限値(この値を超えるとGCが発動します)
34 '※バイト単位
35 limitMemorySize = 1024*1024*30 As LONG_PTR
36
37Public
38 Sub _System_CGarbageCollection()
39 If ppPtr Then Exit Sub
40
41 ppPtr=HeapAlloc(_System_hProcessHeap,0,1)
42 pSize=HeapAlloc(_System_hProcessHeap,0,1)
43 pbFlags=HeapAlloc(_System_hProcessHeap,0,1)
44 n=0
45
46 iAllSize=0
47
48 'スレッド情報管理用オブジェクトを生成
49 _System_pobj_AllThreads=_System_malloc(SizeOf(_System_CThreadCollection)+SizeOf(LONG_PTR))
50 _System_pobj_AllThreads->_System_CThreadCollection()
51
52 'クリティカルセッションを生成
53 InitializeCriticalSection(CriticalSection)
54
55
56 '---------------------------
57 ' 開始時のスレッドを通知
58 '---------------------------
59 Dim hTargetThread As HANDLE
60 DuplicateHandle(GetCurrentProcess(),
61 GetCurrentThread(),
62 GetCurrentProcess(),
63 hTargetThread, 0, FALSE, DUPLICATE_SAME_ACCESS) 'カレントスレッドのハンドルを複製
64
65
66 '自身のThreadオブジェクトを生成
67 Dim obj_Thread As Thread(hTargetThread,GetCurrentThreadId(),0)
68
69 _System_pobj_AllThreads->BeginThread(obj_Thread,_System_gc_StackRoot_StartPtr As *LONG_PTR)
70 End Sub
71 Sub ~_System_CGarbageCollection()
72 If ppPtr=0 Then Exit Sub
73
74#ifdef _DLL
75 _destructor()
76#else
77 '解放スレッドを生成
78 Dim hThread As HANDLE
79 Dim ThreadId As DWord
80 hThread=_beginthreadex(NULL,0,AddressOf(DestructorThread),VarPtr(This),0,ThreadId)
81 CloseHandle(hThread)
82 Sleep( INFINITE )
83#endif
84
85 End Sub
86
87Private
88 Sub _destructor()
89 Dim i As Long
90 For i=0 To ELM(n)
91 If ppPtr[i] Then HeapFree(_System_hProcessHeap,0,ppPtr[i])
92 Next
93 HeapFree(_System_hProcessHeap,0,ppPtr)
94 ppPtr=0
95
96 HeapFree(_System_hProcessHeap,0,pSize)
97 pSize=0
98 HeapFree(_System_hProcessHeap,0,pbFlags)
99 pbFlags=0
100
101 'スレッド情報管理用オブジェクトを破棄
102 _System_pobj_AllThreads->Finalize()
103 _System_free(_System_pobj_AllThreads)
104 _System_pobj_AllThreads=0
105
106 'クリティカルセッションを破棄
107 DeleteCriticalSection(CriticalSection)
108 End Sub
109 Function Cdecl DestructorThread() As Long
110 '-------------------------------------
111 ' すべてのスレッドを一時停止
112 '-------------------------------------
113 _System_pobj_AllThreads->SuspendAllThread()
114
115 _destructor()
116
117 'プロセスを終了
118 ExitProcess(0)
119 End Function
120Public
121
122
123
124 Sub add(new_ptr As VoidPtr, size As SIZE_T,flags As Byte)
125 iAllSize+=size
126
127 Dim i As Long
128 For i=0 To ELM(n)
129 If ppPtr[i]=0 Then
130 ppPtr[i]=new_ptr
131 pSize[i]=size
132 pbFlags[i]=flags
133 Exit Sub
134 End If
135 Next
136
137 ppPtr=HeapReAlloc(_System_hProcessHeap,0,ppPtr,(n+1)*SizeOf(VoidPtr))
138 ppPtr[n]=new_ptr
139
140 pSize=HeapReAlloc(_System_hProcessHeap,0,pSize,(n+1)*SizeOf(SIZE_T))
141 pSize[n]=size
142
143 pbFlags=HeapReAlloc(_System_hProcessHeap,0,pbFlags,(n+1)*SizeOf(Byte))
144 pbFlags[n]=flags
145
146 n++
147 End Sub
148
149
150 Function __malloc(size As SIZE_T,flags As Byte) As VoidPtr
151 EnterCriticalSection(CriticalSection)
152 Dim dwFlags As DWord
153 If flags and _System_GC_FLAG_INITZERO Then
154 dwFlags=HEAP_ZERO_MEMORY
155 Else
156 dwFlags=0
157 End If
158
159
160 Dim pTemp As VoidPtr
161 pTemp=HeapAlloc(_System_hProcessHeap,dwFlags,size)
162 add(pTemp,size,flags)
163 LeaveCriticalSection(CriticalSection)
164 Return pTemp
165 End Function
166
167 Function __realloc(lpMem As VoidPtr, size As SIZE_T) As VoidPtr
168 EnterCriticalSection(CriticalSection)
169 Dim i As Long
170 For i=0 To ELM(n)
171 If ppPtr[i]=lpMem Then
172 iAllSize+=size-pSize[i]
173
174 pSize[i]=size
175 ppPtr[i]=HeapReAlloc(_System_hProcessHeap,HEAP_ZERO_MEMORY,lpMem,size)
176
177 LeaveCriticalSection(CriticalSection)
178 Return ppPtr[i]
179 End If
180 Next
181 LeaveCriticalSection(CriticalSection)
182 Return 0
183 End Function
184
185 Sub __free(lpMem As VoidPtr)
186 EnterCriticalSection(CriticalSection)
187 Dim i As Long
188 For i=0 To ELM(n)
189 If ppPtr[i]=lpMem Then
190 If pbFlags[i] and _System_GC_FLAG_NEEDFREE Then
191 iAllSize-=pSize[i]
192
193 HeapFree(_System_hProcessHeap,0,ppPtr[i])
194 ppPtr[i]=0
195 pSize[i]=0
196 Else
197 OutputDebugString(Ex"GCが管理しているメモリ空間を解放しようとしました。\r\n")
198 End If
199 End If
200 Next
201 LeaveCriticalSection(CriticalSection)
202 End Sub
203
204 Sub sweep()
205 EnterCriticalSection(CriticalSection)
206
207 If iAllSize<limitMemorySize Then
208 'メモリ使用量が上限値を超えていないとき
209 LeaveCriticalSection(CriticalSection)
210 Exit Sub
211 End If
212
213 Dim hThread As HANDLE
214 Dim ThreadId As DWord
215 hThread=_beginthreadex(NULL,0,AddressOf(SweepOnOtherThread),VarPtr(This),0,ThreadId)
216 WaitForSingleObject(hThread,INFINITE)
217 CloseHandle(hThread)
218
219 LeaveCriticalSection(CriticalSection)
220 End Sub
221
222 Function Cdecl SweepOnOtherThread() As Long
223
224 '-------------------------------------
225 ' すべてのスレッドを一時停止
226 '-------------------------------------
227 _System_pobj_AllThreads->SuspendAllThread()
228
229
230 'マークリストを生成
231 pbMark=HeapAlloc(_System_hProcessHeap,HEAP_ZERO_MEMORY,n*SizeOf(Byte))
232
233
234 '-----------------------------------------------
235 ' グローバル領域をルートに指定してスキャン
236 '-----------------------------------------------
237 scan(_System_gc_GlobalRoot_StartPtr,_System_gc_GlobalRoot_Size)
238
239 '-----------------------------------------------
240 'ローカル領域をルートに指定してスキャン
241 '-----------------------------------------------
242 Dim Context As CONTEXT
243 Dim NowSp As *LONG_PTR
244 Dim size As LONG_PTR
245 Dim i As Long
246 For i=0 To ELM(_System_pobj_AllThreads->ThreadNum)
247 If _System_pobj_AllThreads->ppobj_Thread[i] Then
248 FillMemory(VarPtr(Context),SizeOf(CONTEXT),0)
249 Context.ContextFlags=CONTEXT_CONTROL
250 If _System_pobj_AllThreads->ppobj_Thread[i]->__GetContext(Context)=0 Then
251 OutputDebugString(Ex"レジスタ情報の取得に失敗しました。\r\n")
252 End If
253
254#ifdef _WIN64
255 NowSp=Context.Rsp As *LONG_PTR
256#else
257 NowSp=Context.Esp As *LONG_PTR
258#endif
259
260 size=(_System_pobj_AllThreads->pStackBase[i] As LONG_PTR)-(NowSp As LONG_PTR)
261
262 scan(NowSp,size)
263 End If
264 Next
265
266
267 Dim iBackAllSize As SIZE_T
268 iBackAllSize=iAllSize
269
270 '使われていないメモリを解放する
271 For i=0 To ELM(n)
272 If pbMark[i]=0 and ppPtr[i]<>0 and (pbFlags[i] and _System_GC_FLAG_NEEDFREE)=0 Then
273 iAllSize-=pSize[i]
274
275 HeapFree(_System_hProcessHeap,0,ppPtr[i])
276 ppPtr[i]=0
277 pSize[i]=0
278 End If
279 Next
280
281 'マークリストを解放
282 HeapFree(_System_hProcessHeap,0,pbMark)
283
284 If iBackAllSize=iAllSize Then
285 '許容量を拡張する
286 limitMemorySize*=2
287 End If
288
289
290 '-------------------------------------
291 ' すべてのスレッドを再開
292 '-------------------------------------
293 _System_pobj_AllThreads->ResumeAllThread()
294 End Function
295
296
297Private
298
299 pbMark As *Byte
300
301 Function HitTest(pSample As VoidPtr) As Long
302 Dim i As Long
303 For i=0 To ELM(n)
304 If (ppPtr[i] As LONG_PTR)<=(pSample As LONG_PTR) and (pSample As LONG_PTR)<((ppPtr[i] As LONG_PTR)+pSize[i]) Then
305 Return i
306 End If
307 Next
308 Return -1
309 End Function
310
311 Sub scan(pStartPtr As *LONG_PTR, size As LONG_PTR)
312 Dim i As Long, count As Long, index As Long
313 count=(size\SizeOf(LONG_PTR)) As Long
314 For i=0 To ELM(count)
315 index=HitTest(pStartPtr[i] As VoidPtr)
316 If index<>-1 Then
317 If pbMark[index]=0 Then
318 pbMark[index]=1
319
320 If (pbFlags[index] and _System_GC_FLAG_ATOMIC)=0 Then
321 'ヒープ領域がポインタ値を含む可能性があるとき
322 scan(ppPtr[index] As *LONG_PTR,pSize[index])
323 End If
324 End If
325 End If
326 Next
327 End Sub
328End Class
329
330'GC管理用の特殊なシステムオブジェクト(デストラクタは最終のタイミングで呼び出されます)
331Dim _System_GC As _System_CGarbageCollection
332
333
334
335Function GC_malloc(size As Long) As VoidPtr
336 ' sweep
337 _System_GC.sweep()
338
339 'allocate
340 Return _System_GC.__malloc(size,0)
341End Function
342
343Function GC_malloc_atomic(size As Long) As VoidPtr
344 ' sweep
345 _System_GC.sweep()
346
347 'allocate
348 Return _System_GC.__malloc(size,_System_GC_FLAG_ATOMIC)
349End Function
Note: See TracBrowser for help on using the repository browser.