source: Include/system/gc.sbp@ 18

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