source: Include/system/gc.sbp@ 79

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

Booleanがコンパイラで実装されたので、TypeDefを削除。
DLLコンパイル時にGCの破棄部分が正常に働かないバグを修正。
TraceListener周りを修正。

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